From 3c7f0fcc082b09c01928258476724878e22c7807 Mon Sep 17 00:00:00 2001 From: Prakash M Bailkeri Date: Thu, 19 Nov 2015 22:30:37 +0530 Subject: [PATCH] Routing policy code changes Initial version of the config handling code for Routing Policy Change-Id: I65ae7e7ea8f4a3b6af42202ddc267874733a13af Closes-bug: #1500698 --- src/bgp/SConscript | 2 + src/bgp/bgp_config.cc | 22 ++ src/bgp/bgp_config.h | 78 ++++ src/bgp/bgp_config_ifmap.cc | 450 ++++++++++++++++++++++- src/bgp/bgp_config_ifmap.h | 106 ++++++ src/bgp/bgp_config_listener.cc | 14 +- src/bgp/bgp_config_parser.cc | 50 +++ src/bgp/bgp_config_parser.h | 2 + src/bgp/bgp_config_yaml.cc | 26 ++ src/bgp/bgp_factory.cc | 3 + src/bgp/bgp_factory.h | 2 + src/bgp/bgp_server.cc | 14 + src/bgp/bgp_server.h | 6 + src/bgp/daemon/SConscript | 2 + src/bgp/ermvpn/test/SConscript | 2 + src/bgp/evpn/test/SConscript | 2 + src/bgp/inet/test/SConscript | 2 + src/bgp/inet6/test/SConscript | 2 + src/bgp/inet6vpn/test/SConscript | 2 + src/bgp/l3vpn/test/SConscript | 2 + src/bgp/routing-policy/SConscript | 16 + src/bgp/routing-policy/routing_policy.cc | 16 + src/bgp/routing-policy/routing_policy.h | 26 ++ src/bgp/rtarget/test/SConscript | 3 +- src/bgp/test/SConscript | 3 +- src/bgp/test/bgp_config_mock.cc | 12 + src/bgp/test/bgp_config_test.cc | 38 ++ src/bgp/testdata/routing_policy_0.xml | 30 ++ src/bgp/testdata/routing_policy_1.xml | 36 ++ src/bgp/testdata/routing_policy_2.xml | 53 +++ src/control-node/SConscript | 3 + 31 files changed, 1021 insertions(+), 4 deletions(-) create mode 100644 src/bgp/routing-policy/SConscript create mode 100644 src/bgp/routing-policy/routing_policy.cc create mode 100644 src/bgp/routing-policy/routing_policy.h create mode 100644 src/bgp/testdata/routing_policy_0.xml create mode 100644 src/bgp/testdata/routing_policy_1.xml create mode 100644 src/bgp/testdata/routing_policy_2.xml diff --git a/src/bgp/SConscript b/src/bgp/SConscript index 01b740f3c63..e65e79b9f20 100644 --- a/src/bgp/SConscript +++ b/src/bgp/SConscript @@ -110,6 +110,8 @@ test_suite += env.SConscript('l3vpn/SConscript', exports='BuildEnv', duplicate = 0) test_suite += env.SConscript('origin-vn/SConscript', exports='BuildEnv', duplicate = 0) +env.SConscript('routing-policy/SConscript', exports='BuildEnv', duplicate = 0) + env.SConscript('routing-instance/SConscript', exports='BuildEnv', duplicate = 0) test_suite += env.SConscript('rtarget/SConscript', exports='BuildEnv', duplicate = 0) diff --git a/src/bgp/bgp_config.cc b/src/bgp/bgp_config.cc index 4f9d66b7431..1ab6146c3a0 100644 --- a/src/bgp/bgp_config.cc +++ b/src/bgp/bgp_config.cc @@ -285,6 +285,19 @@ const ServiceChainConfig *BgpInstanceConfig::service_chain_info( return NULL; } + +BgpRoutingPolicyConfig::BgpRoutingPolicyConfig(const std::string &name) + : name_(name), + last_change_at_(UTCTimestampUsec()) { +} + +BgpRoutingPolicyConfig::~BgpRoutingPolicyConfig() { +} + +void BgpRoutingPolicyConfig::Clear() { + terms_.clear(); +} + BgpConfigManager::BgpConfigManager(BgpServer *server) : server_(server) { } @@ -301,6 +314,15 @@ void BgpConfigManager::Notify( } } +template<> +void BgpConfigManager::Notify( + const BgpRoutingPolicyConfig *config, EventType event) { + config->set_last_change_at(UTCTimestampUsec()); + if (obs_.policy) { + (obs_.policy)(config, event); + } +} + template<> void BgpConfigManager::Notify( const BgpProtocolConfig *config, EventType event) { diff --git a/src/bgp/bgp_config.h b/src/bgp/bgp_config.h index 299c02759e4..ded0d73e0e3 100644 --- a/src/bgp/bgp_config.h +++ b/src/bgp/bgp_config.h @@ -262,12 +262,73 @@ struct StaticRouteConfig { std::vector route_target; }; +typedef std::vector CommunityList; + +struct PrefixMatch { + std::string prefix_to_match; + std::string prefix_match_type; +}; + +struct RoutingPolicyMatch { + std::string community_match; + PrefixMatch prefix_match; +}; + +struct ActionUpdate { + CommunityList community_set; + CommunityList community_add; + CommunityList community_remove; + uint32_t local_pref; +}; + +struct RoutingPolicyAction { + enum ActionType { + ACCEPT, + REJECT, + NEXT_TERM + }; + ActionUpdate update; + ActionType action; +}; + +struct RoutingPolicyTerm { + RoutingPolicyMatch match; + RoutingPolicyAction action; +}; + +// Route Policy configuration. +class BgpRoutingPolicyConfig { +public: + typedef std::vector RoutingPolicyTermList; + explicit BgpRoutingPolicyConfig(const std::string &name); + virtual ~BgpRoutingPolicyConfig(); + + const std::string &name() const { return name_; } + void set_last_change_at(uint64_t tstamp) const { last_change_at_ = tstamp; } + void add_term(RoutingPolicyTerm term) { + terms_.push_back(term); + } + void Clear(); + +private: + std::string name_; + mutable uint64_t last_change_at_; + RoutingPolicyTermList terms_; + DISALLOW_COPY_AND_ASSIGN(BgpRoutingPolicyConfig); +}; + +struct RoutingPolicyAttachInfo { + std::string sequence_; + std::string routing_policy_; +}; + // Instance configuration. class BgpInstanceConfig { public: typedef std::set RouteTargetList; typedef std::vector StaticRouteList; typedef std::vector ServiceChainList; + typedef std::vector RoutingPolicyList; explicit BgpInstanceConfig(const std::string &name); virtual ~BgpInstanceConfig(); @@ -320,6 +381,12 @@ class BgpInstanceConfig { } const ServiceChainConfig *service_chain_info(Address::Family family) const; + const RoutingPolicyList &routing_policy_list() const { + return routing_policies_; + } + void swap_routing_policy_list(RoutingPolicyList *list) { + std::swap(routing_policies_, *list); + } void Clear(); private: @@ -337,6 +404,7 @@ class BgpInstanceConfig { StaticRouteList inet_static_routes_; StaticRouteList inet6_static_routes_; ServiceChainList service_chain_list_; + RoutingPolicyList routing_policies_; DISALLOW_COPY_AND_ASSIGN(BgpInstanceConfig); }; @@ -411,13 +479,19 @@ class BgpConfigManager { BgpInstanceObserver; typedef boost::function BgpNeighborObserver; + typedef boost::function + BgpRoutingPolicyObserver; struct Observers { BgpProtocolObserver protocol; BgpInstanceObserver instance; BgpNeighborObserver neighbor; + BgpRoutingPolicyObserver policy; }; + typedef std::map RoutingPolicyMap; + typedef std::pair RoutingPolicyMapRange; typedef std::map InstanceMap; typedef std::pair InstanceMapRange; @@ -437,6 +511,8 @@ class BgpConfigManager { virtual void Terminate() = 0; virtual const std::string &localname() const = 0; + virtual RoutingPolicyMapRange RoutingPolicyMapItems( + const std::string &start_policy = std::string()) const = 0; virtual InstanceMapRange InstanceMapItems( const std::string &start_instance = std::string()) const = 0; virtual NeighborMapRange NeighborMapItems( @@ -446,6 +522,8 @@ class BgpConfigManager { virtual const BgpInstanceConfig *FindInstance( const std::string &name) const = 0; + virtual const BgpRoutingPolicyConfig *FindRoutingPolicy( + const std::string &name) const = 0; virtual const BgpProtocolConfig *GetProtocolConfig( const std::string &instance_name) const = 0; virtual const BgpNeighborConfig *FindNeighbor( diff --git a/src/bgp/bgp_config_ifmap.cc b/src/bgp/bgp_config_ifmap.cc index 1ca6a71e000..2694e11e52a 100644 --- a/src/bgp/bgp_config_ifmap.cc +++ b/src/bgp/bgp_config_ifmap.cc @@ -65,6 +65,53 @@ void BgpIfmapPeeringConfig::SetNodeProxy(IFMapNodeProxy *proxy) { } } +BgpIfmapRoutingPolicyLinkConfig::BgpIfmapRoutingPolicyLinkConfig( + BgpIfmapInstanceConfig *rti, BgpIfmapRoutingPolicyConfig *rtp) : + instance_(rti), policy_(rtp) { +} + +BgpIfmapRoutingPolicyLinkConfig::~BgpIfmapRoutingPolicyLinkConfig() { +} + +void BgpIfmapRoutingPolicyLinkConfig::SetNodeProxy(IFMapNodeProxy *proxy) { + if (proxy != NULL) { + node_proxy_.Swap(proxy); + name_ = node_proxy_.node()->name(); + } +} + +bool +BgpIfmapRoutingPolicyLinkConfig::GetRoutingInstanceRoutingPolicyPair(DBGraph *graph, + IFMapNode *node, pair *pair) { + IFMapNode *routing_instance = NULL; + IFMapNode *routing_policy = NULL; + + for (DBGraphVertex::adjacency_iterator iter = node->begin(graph); + iter != node->end(graph); ++iter) { + IFMapNode *adj = static_cast(iter.operator->()); + if (strcmp(adj->table()->Typename(), "routing-instance") == 0) + routing_instance = adj; + if (strcmp(adj->table()->Typename(), "routing-policy") == 0) + routing_policy = adj; + } + if (routing_policy == NULL || routing_instance == NULL) { + return false; + } + + pair->first = routing_instance; + pair->second = routing_policy; + return true; +} + +void BgpIfmapRoutingPolicyLinkConfig::Update(BgpIfmapConfigManager *manager, + const autogen::RoutingInstanceRoutingPolicy *ri_rp) { + ri_rp_link_.reset(ri_rp); +} + +void BgpIfmapRoutingPolicyLinkConfig::Delete(BgpIfmapConfigManager *manager) { + ri_rp_link_.reset(); +} + static AuthenticationData::KeyType KeyChainType(const std::string &value) { // Case-insensitive comparison if (boost::iequals(value, "md5")) { @@ -586,6 +633,28 @@ static void GetRoutingInstanceExportTargets(DBGraph *graph, IFMapNode *node, } } +// +// Fill in all the routing-policies for a routing-instance. The input +// IFMapNode represents the routing-instance-routing-policy. We traverse to +// graph edges and look for routing-policy adjacency +// +static void GetRoutingInstanceRoutingPolicy(DBGraph *graph, IFMapNode *node, + RoutingPolicyAttachInfo *routing_policy) { + std::string sequence; + const autogen::RoutingInstanceRoutingPolicy *policy = + static_cast(node->GetObject()); + const autogen::RoutingPolicyType &attach_info = policy->data(); + routing_policy->sequence_ = attach_info.sequence; + for (DBGraphVertex::adjacency_iterator iter = node->begin(graph); + iter != node->end(graph); ++iter) { + IFMapNode *adj = static_cast(iter.operator->()); + if (strcmp(adj->table()->Typename(), "routing-policy") == 0) { + routing_policy->routing_policy_ = adj->name(); + return; + } + } +} + // // Get the network id for a virtual-network. The input IFMapNode represents // the virtual-network. @@ -703,6 +772,63 @@ static void SetServiceChainConfig(BgpInstanceConfig *rti, rti->swap_service_chain_list(&list); } +void BgpIfmapConfigManager::ProcessRoutingPolicyLink(const BgpConfigDelta &delta) { + CHECK_CONCURRENCY("bgp::Config"); + + BgpIfmapRoutingPolicyLinkConfig *ri_rp_link + = config_->FindRoutingPolicyLink(delta.id_name); + if (ri_rp_link == NULL) { + IFMapNodeProxy *proxy = delta.node.get(); + if (proxy == NULL) { + return; + } + IFMapNode *node = proxy->node(); + if (node == NULL || delta.obj.get() == NULL) { + return; + } + + pair ri_rp_pair; + if (!BgpIfmapRoutingPolicyLinkConfig::GetRoutingInstanceRoutingPolicyPair( + db_graph_, node, &ri_rp_pair)) { + return; + } + + std::string instance_name = ri_rp_pair.first->name(); + std::string policy_name = ri_rp_pair.second->name(); + + BgpIfmapInstanceConfig *rti = + config_->FindInstance(instance_name); + BgpIfmapRoutingPolicyConfig *rtp = + config_->FindRoutingPolicy(policy_name); + if (!rti || !rtp) { + return; + } + + ri_rp_link = config_->CreateRoutingPolicyLink(rti, rtp, proxy); + } else { + const IFMapNode *node = ri_rp_link->node(); + assert(node != NULL); + if (delta.obj.get() == NULL) { + BgpIfmapRoutingPolicyConfig *rtp = ri_rp_link->policy(); + BgpIfmapInstanceConfig *rti = ri_rp_link->instance(); + config_->DeleteRoutingPolicyLink(ri_rp_link); + if (rtp->DeleteIfEmpty(this)) { + config_->DeleteRoutingPolicy(rtp); + } + if (rti->DeleteIfEmpty(this)) { + BGP_CONFIG_LOG_INSTANCE(Delete, server(), rti, + SandeshLevel::SYS_DEBUG, BGP_LOG_FLAG_ALL); + config_->DeleteInstance(rti); + } + return; + } + } + + autogen::RoutingInstanceRoutingPolicy *ri_rp_link_cfg = + static_cast(delta.obj.get()); + + ri_rp_link->Update(this, ri_rp_link_cfg); +} // // Update BgpIfmapInstanceConfig based on a new autogen::RoutingInstance object. // @@ -719,6 +845,7 @@ static void SetServiceChainConfig(BgpInstanceConfig *rti, void BgpIfmapInstanceConfig::Update(BgpIfmapConfigManager *manager, const autogen::RoutingInstance *config) { BgpInstanceConfig::RouteTargetList import_list, export_list; + BgpInstanceConfig::RoutingPolicyList policy_list; data_.Clear(); DBGraph *graph = manager->graph(); @@ -743,6 +870,11 @@ void BgpIfmapInstanceConfig::Update(BgpIfmapConfigManager *manager, export_list.insert(target); } } + } else if (strcmp(adj->table()->Typename(), + "routing-instance-routing-policy") == 0) { + RoutingPolicyAttachInfo policy_info; + GetRoutingInstanceRoutingPolicy(graph, adj, &policy_info); + policy_list.push_back(policy_info); } else if (strcmp(adj->table()->Typename(), "routing-instance") == 0) { vector target_list; GetRoutingInstanceExportTargets(graph, adj, &target_list); @@ -760,6 +892,7 @@ void BgpIfmapInstanceConfig::Update(BgpIfmapConfigManager *manager, data_.set_import_list(import_list); data_.set_export_list(export_list); + data_.swap_routing_policy_list(&policy_list); if (config) { data_.set_has_pnf(config->has_pnf()); @@ -786,7 +919,8 @@ bool BgpIfmapInstanceConfig::DeleteIfEmpty(BgpConfigManager *manager) { if (node() != NULL || protocol_.get() != NULL) { return false; } - if (!neighbors_.empty() || !peerings_.empty()) { + if (!neighbors_.empty() || !peerings_.empty() || + !routing_policies_.empty()) { return false; } @@ -886,6 +1020,20 @@ void BgpIfmapInstanceConfig::DeletePeering(BgpIfmapPeeringConfig *peering) { peerings_.erase(peering->name()); } +// +// Add a BgpIfmapRoutingPolicyConfig to this BgpIfmapInstanceConfig. +// +void BgpIfmapInstanceConfig::AddRoutingPolicy(BgpIfmapRoutingPolicyConfig *rtp) { + routing_policies_.insert(make_pair(rtp->name(), rtp)); +} + +// +// Delete a BgpIfmapRoutingPolicyConfig from this BgpIfmapInstanceConfig. +// +void BgpIfmapInstanceConfig::DeleteRoutingPolicy(BgpIfmapRoutingPolicyConfig *rtp) { + routing_policies_.erase(rtp->name()); +} + // // Constructor for BgpIfmapConfigData. // @@ -966,6 +1114,69 @@ BgpIfmapInstanceConfig::NeighborMapItems() const { return make_pair(neighbors_.begin(), neighbors_.end()); } +// +// Create a new BgpIfmapRoutingPolicyLinkConfig. +// +// The IFMapNodeProxy is a proxy for the IFMapNode which is the +// midnode that represents the routing-instance-routing-policy. The newly created +// BgpIfmapRoutingPolicyLinkConfig gets added to the IfmapRoutingPolicyLinkMap. +// +BgpIfmapRoutingPolicyLinkConfig * +BgpIfmapConfigData::CreateRoutingPolicyLink(BgpIfmapInstanceConfig *rti, + BgpIfmapRoutingPolicyConfig *rtp, + IFMapNodeProxy *proxy) { + BgpIfmapRoutingPolicyLinkConfig *ri_rp_link = + new BgpIfmapRoutingPolicyLinkConfig(rti, rtp); + ri_rp_link->SetNodeProxy(proxy); + pair result = + ri_rp_links_.insert(make_pair(ri_rp_link->node()->name(), ri_rp_link)); + assert(result.second); + ri_rp_link->instance()->AddRoutingPolicy(rtp); + ri_rp_link->policy()->AddInstance(rti); + return ri_rp_link; +} + +// +// Delete a BgpIfmapRoutingPolicyLinkConfig. +// +// The BgpIfmapRoutingPolicyLinkConfig is removed from the +// IfmapRoutingPolicyLinkMap and then deleted. +// Note that the reference to the IFMapNode for the routing-instance-routing-policy +// gets released via the destructor when the IFMapNodeProxy is destroyed. +// +void BgpIfmapConfigData::DeleteRoutingPolicyLink(BgpIfmapRoutingPolicyLinkConfig + *ri_rp_link) { + ri_rp_links_.erase(ri_rp_link->node()->name()); + ri_rp_link->instance()->DeleteRoutingPolicy(ri_rp_link->policy()); + ri_rp_link->policy()->RemoveInstance(ri_rp_link->instance()); + delete ri_rp_link; +} + +// +// Find the BgpIfmapRoutingPolicyLinkConfig by name. +// +BgpIfmapRoutingPolicyLinkConfig * +BgpIfmapConfigData::FindRoutingPolicyLink(const string &name) { + IfmapRoutingPolicyLinkMap::iterator loc = ri_rp_links_.find(name); + if (loc != ri_rp_links_.end()) { + return loc->second; + } + return NULL; +} + +// +// Find the BgpIfmapRoutingPolicyLinkConfig by name. +// Const version. +// +const BgpIfmapRoutingPolicyLinkConfig * +BgpIfmapConfigData::FindRoutingPolicyLink(const string &name) const { + IfmapRoutingPolicyLinkMap::const_iterator loc = ri_rp_links_.find(name); + if (loc != ri_rp_links_.end()) { + return loc->second; + } + return NULL; +} + // // Create a new BgpIfmapPeeringConfig. // @@ -1027,6 +1238,66 @@ BgpIfmapConfigData::InstanceMapItems(const string &start_name) const { instance_config_map_.end()); } +BgpConfigManager::RoutingPolicyMapRange +BgpIfmapConfigData::RoutingPolicyMapItems(const string &start_name) const { + return make_pair(routing_policy_config_map_.lower_bound(start_name), + routing_policy_config_map_.end()); +} + +// +// Locate the BgpIfmapRoutingPolicyConfig by name, create it if not found. +// The newly created BgpIfmapRoutingPolicyConfig gets added to the +// IfmapRoutingPolicyMap. +// +BgpIfmapRoutingPolicyConfig *BgpIfmapConfigData::LocateRoutingPolicy(const string &name) { + BgpIfmapRoutingPolicyConfig *rtp = FindRoutingPolicy(name); + if (rtp != NULL) { + return rtp; + } + rtp = new BgpIfmapRoutingPolicyConfig(name); + pair result = + routing_policies_.insert(make_pair(name, rtp)); + assert(result.second); + pair result2 = + routing_policy_config_map_.insert( + make_pair(name, rtp->routing_policy_config())); + assert(result2.second); + return rtp; +} + +// +// Remove the given BgpIfmapRoutingPolicyConfig from the IfmapRoutingPolicyMap +// and delete it. +// +void BgpIfmapConfigData::DeleteRoutingPolicy(BgpIfmapRoutingPolicyConfig *rtp) { + IfmapRoutingPolicyMap::iterator loc = routing_policies_.find(rtp->name()); + assert(loc != routing_policies_.end()); + routing_policies_.erase(loc); + BgpRoutingPolicyMap::iterator loc2 = + routing_policy_config_map_.find(rtp->name()); + assert(loc2 != routing_policy_config_map_.end()); + routing_policy_config_map_.erase(loc2); + delete rtp; +} + +BgpIfmapRoutingPolicyConfig *BgpIfmapConfigData::FindRoutingPolicy( + const std::string &name) { + IfmapRoutingPolicyMap::iterator loc = routing_policies_.find(name); + if (loc != routing_policies_.end()) { + return loc->second; + } + return NULL; +} + +const BgpIfmapRoutingPolicyConfig *BgpIfmapConfigData::FindRoutingPolicy( + const std::string &name) const { + IfmapRoutingPolicyMap::const_iterator loc = routing_policies_.find(name); + if (loc != routing_policies_.end()) { + return loc->second; + } + return NULL; +} + // // Constructor for BgpIfmapConfigManager. // @@ -1077,6 +1348,11 @@ BgpIfmapConfigManager::InstanceMapItems(const string &start_name) const { return config_->InstanceMapItems(start_name); } +BgpConfigManager::RoutingPolicyMapRange +BgpIfmapConfigManager::RoutingPolicyMapItems(const string &start_name) const { + return config_->RoutingPolicyMapItems(start_name); +} + BgpConfigManager::NeighborMapRange BgpIfmapConfigManager::NeighborMapItems( const std::string &instance_name) const { @@ -1097,6 +1373,126 @@ int BgpIfmapConfigManager::NeighborCount( return rti->neighbors().size(); } +// +// Constructor for BgpIfmapRoutingPolicyConfig. +// +BgpIfmapRoutingPolicyConfig::BgpIfmapRoutingPolicyConfig(const std::string &name) + : name_(name), + data_(name) { +} + +// +// Destructor for BgpIfmapRoutingPolicyConfig. +// +BgpIfmapRoutingPolicyConfig::~BgpIfmapRoutingPolicyConfig() { +} + +// +// Set the IFMapNodeProxy for the BgpIfmapRoutingPolicyConfig. +// +void BgpIfmapRoutingPolicyConfig::SetNodeProxy(IFMapNodeProxy *proxy) { + if (proxy != NULL) { + node_proxy_.Swap(proxy); + } +} + +void BgpIfmapRoutingPolicyConfig::Delete(BgpConfigManager *manager) { + manager->Notify(&data_, BgpConfigManager::CFG_DELETE); + routing_policy_.reset(); +} + +// +// Return true if the BgpIfmapRoutingPolicyConfig is ready to be deleted. +// The caller is responsible for actually deleting it. +// +bool BgpIfmapRoutingPolicyConfig::DeleteIfEmpty(BgpConfigManager *manager) { + if (node() != NULL) { + return false; + } + if (!instances_.empty()) { + return false; + } + + Delete(manager); + return true; +} + +// +// Add a BgpIfmapInstanceConfig to BgpIfmapRoutingPolicyConfig. +// +void BgpIfmapRoutingPolicyConfig::AddInstance(BgpIfmapInstanceConfig *rti) { + instances_.insert(make_pair(rti->name(), rti)); +} + +// +// Remove a BgpIfmapInstanceConfig to BgpIfmapRoutingPolicyConfig. +// +void BgpIfmapRoutingPolicyConfig::RemoveInstance(BgpIfmapInstanceConfig *rti) { + instances_.erase(rti->name()); +} + + +static void BuildPolicyTerm(autogen::PolicyTerm cfg_term, + RoutingPolicyTerm *term) { + term->match.community_match = cfg_term.fromxx.community; + term->match.prefix_match.prefix_to_match = cfg_term.fromxx.prefix.prefix; + term->match.prefix_match.prefix_match_type = cfg_term.fromxx.prefix.type_; + BOOST_FOREACH(const std::string community, + cfg_term.then.update.community.add.community) { + term->action.update.community_add.push_back(community); + } + BOOST_FOREACH(const std::string community, + cfg_term.then.update.community.remove.community) { + term->action.update.community_remove.push_back(community); + } + BOOST_FOREACH(const std::string community, + cfg_term.then.update.community.set.community) { + term->action.update.community_set.push_back(community); + } + term->action.update.local_pref = cfg_term.then.update.local_pref; + term->action.action = RoutingPolicyAction::ACCEPT; + if (strcmp(cfg_term.then.action.c_str(), "reject") == 0) { + term->action.action = RoutingPolicyAction::REJECT; + } else if (strcmp(cfg_term.then.action.c_str(), "next") == 0) { + term->action.action = RoutingPolicyAction::NEXT_TERM; + } +} + +static void BuildPolicyTerms(BgpRoutingPolicyConfig *policy_cfg, + const autogen::RoutingPolicy *policy) { + std::vector terms = policy->entries(); + BOOST_FOREACH(autogen::PolicyTerm cfg_term, terms) { + RoutingPolicyTerm policy_term; + BuildPolicyTerm(cfg_term, &policy_term); + policy_cfg->add_term(policy_term); + } +} + +void BgpIfmapRoutingPolicyConfig::Update(BgpIfmapConfigManager *manager, + const autogen::RoutingPolicy *policy) { + routing_policy_.reset(policy); + data_.Clear(); + if (policy) { + BuildPolicyTerms(&data_, policy); + } +} + +// +// Reset IFMap related state in the BgpIfmapRoutingPolicyConfig. +// +void BgpIfmapRoutingPolicyConfig::ResetConfig() { + node_proxy_.Clear(); +} + +const BgpRoutingPolicyConfig *BgpIfmapConfigManager::FindRoutingPolicy( + const std::string &name) const { + BgpIfmapRoutingPolicyConfig *rtp = config_->FindRoutingPolicy(name); + if (rtp == NULL) { + return NULL; + } + return rtp->routing_policy_config(); +} + const BgpInstanceConfig *BgpIfmapConfigManager::FindInstance( const std::string &name) const { BgpIfmapInstanceConfig *rti = config_->FindInstance(name); @@ -1181,6 +1577,10 @@ void BgpIfmapConfigManager::IdentifierMapInit() { id_map_.insert(make_pair("routing-instance", boost::bind(&BgpIfmapConfigManager::ProcessRoutingInstance, this, _1))); + id_map_.insert(make_pair("routing-policy", + boost::bind(&BgpIfmapConfigManager::ProcessRoutingPolicy, this, _1))); + id_map_.insert(make_pair("routing-instance-routing-policy", + boost::bind(&BgpIfmapConfigManager::ProcessRoutingPolicyLink, this, _1))); id_map_.insert(make_pair("bgp-router", boost::bind(&BgpIfmapConfigManager::ProcessBgpRouter, this, _1))); id_map_.insert(make_pair("bgp-peering", @@ -1375,6 +1775,54 @@ void BgpIfmapConfigManager::ProcessBgpProtocol(const BgpConfigDelta &delta) { } } +// +// Handler for routing policy objects. +// +// BgpConfigListener::DependencyTracker ensures associated routing instances +// are present in the change list. +// +void BgpIfmapConfigManager::ProcessRoutingPolicy(const BgpConfigDelta &delta) { + CHECK_CONCURRENCY("bgp::Config"); + + BgpConfigManager::EventType event = BgpConfigManager::CFG_CHANGE; + string policy_name = delta.id_name; + BgpIfmapRoutingPolicyConfig *rtp = config_->FindRoutingPolicy(policy_name); + if (rtp == NULL) { + IFMapNodeProxy *proxy = delta.node.get(); + if (proxy == NULL) { + return; + } + IFMapNode *node = proxy->node(); + if (node == NULL || node->IsDeleted()) { + return; + } + event = BgpConfigManager::CFG_ADD; + rtp = config_->LocateRoutingPolicy(policy_name); + rtp->SetNodeProxy(proxy); + } else { + IFMapNode *node = rtp->node(); + if (node == NULL) { + IFMapNodeProxy *proxy = delta.node.get(); + if (proxy == NULL) { + return; + } + rtp->SetNodeProxy(proxy); + } else if (node->IsDeleted()) { + rtp->ResetConfig(); + if (rtp->DeleteIfEmpty(this)) { + config_->DeleteRoutingPolicy(rtp); + } + return; + } + } + + autogen::RoutingPolicy *rtp_config = + static_cast(delta.obj.get()); + rtp->Update(this, rtp_config); + Notify(rtp->routing_policy_config(), event); +} + + // // Handler for bgp-router objects. // diff --git a/src/bgp/bgp_config_ifmap.h b/src/bgp/bgp_config_ifmap.h index 90bf954d28a..08a2877c571 100644 --- a/src/bgp/bgp_config_ifmap.h +++ b/src/bgp/bgp_config_ifmap.h @@ -22,6 +22,7 @@ class BgpConfigListener; typedef struct IFMapConfigListener::ConfigDelta BgpConfigDelta; class BgpIfmapConfigManager; class BgpIfmapInstanceConfig; +class BgpIfmapRoutingPolicyConfig; class BgpServer; class DB; class DBGraph; @@ -30,6 +31,8 @@ namespace autogen { class BgpPeering; class BgpRouter; class RoutingInstance; +class RoutingPolicy; +class RoutingInstanceRoutingPolicy; struct BgpRouterParams; } @@ -178,6 +181,7 @@ class BgpIfmapInstanceConfig { public: typedef std::map NeighborMap; typedef std::map PeeringMap; + typedef std::map RouitngPolicyMap; typedef BgpInstanceConfig::RouteTargetList RouteTargetList; explicit BgpIfmapInstanceConfig(const std::string &name); @@ -231,6 +235,8 @@ class BgpIfmapInstanceConfig { return data_.virtual_network(); } int virtual_network_index() const { return data_.virtual_network_index(); } + void AddRoutingPolicy(BgpIfmapRoutingPolicyConfig *rtp); + void DeleteRoutingPolicy(BgpIfmapRoutingPolicyConfig *rtp); private: friend class BgpConfigManagerTest; @@ -241,10 +247,80 @@ class BgpIfmapInstanceConfig { boost::scoped_ptr protocol_; NeighborMap neighbors_; PeeringMap peerings_; + RouitngPolicyMap routing_policies_; DISALLOW_COPY_AND_ASSIGN(BgpIfmapInstanceConfig); }; +class BgpIfmapRoutingPolicyLinkConfig { +public: + explicit BgpIfmapRoutingPolicyLinkConfig(BgpIfmapInstanceConfig *rti, + BgpIfmapRoutingPolicyConfig *rtp); + ~BgpIfmapRoutingPolicyLinkConfig(); + + void SetNodeProxy(IFMapNodeProxy *proxy); + + const IFMapNode *node() const { return node_proxy_.node(); } + std::string name() const { return name_; } + const autogen::RoutingInstanceRoutingPolicy *routing_policy_link() const { + return ri_rp_link_.get(); + } + static bool GetRoutingInstanceRoutingPolicyPair(DBGraph *graph, + IFMapNode *node, std::pair *pair); + BgpIfmapInstanceConfig *instance() { return instance_; } + BgpIfmapRoutingPolicyConfig *policy() { return policy_; } + + void Update(BgpIfmapConfigManager *manager, + const autogen::RoutingInstanceRoutingPolicy *ri_rp); + void Delete(BgpIfmapConfigManager *manager); + +private: + BgpIfmapInstanceConfig *instance_; + BgpIfmapRoutingPolicyConfig *policy_; + std::string name_; + IFMapNodeProxy node_proxy_; + boost::intrusive_ptr ri_rp_link_; + + DISALLOW_COPY_AND_ASSIGN(BgpIfmapRoutingPolicyLinkConfig); +}; + +class BgpIfmapRoutingPolicyConfig { +public: + typedef std::map InstanceMap; + explicit BgpIfmapRoutingPolicyConfig(const std::string &name); + ~BgpIfmapRoutingPolicyConfig(); + + void SetNodeProxy(IFMapNodeProxy *proxy); + + // The corresponding if-map node has been deleted. + void ResetConfig(); + void Delete(BgpConfigManager *manager); + bool DeleteIfEmpty(BgpConfigManager *manager); + + void Update(BgpIfmapConfigManager *manager, + const autogen::RoutingPolicy *policy); + + IFMapNode *node() { return node_proxy_.node(); } + const std::string &name() const { return name_; } + + BgpRoutingPolicyConfig *routing_policy_config() { return &data_; } + const BgpRoutingPolicyConfig *routing_policy_config() const { return &data_; } + + void AddInstance(BgpIfmapInstanceConfig *rti); + void RemoveInstance(BgpIfmapInstanceConfig *rti); +private: + friend class BgpConfigManagerTest; + + std::string name_; + IFMapNodeProxy node_proxy_; + BgpRoutingPolicyConfig data_; + boost::intrusive_ptr routing_policy_; + InstanceMap instances_; + + DISALLOW_COPY_AND_ASSIGN(BgpIfmapRoutingPolicyConfig); +}; + + // // BgpConfigData contains all the configuration data that's relevant to a // node. The BgpConfigManager has a pointer to BgpConfigData. @@ -253,12 +329,17 @@ class BgpIfmapInstanceConfig { // that have been created for all the routing-instances. // The IfmapPeeringMap stores pointers to the BgpIfmapPeeringConfigs // that have been created for all the bgp-peerings. +// The IfmapRoutingPolicyMap stores pointers to the BgpIfmapRoutingPolicyConfig +// that have been created for all the routing-policy. // class BgpIfmapConfigData { public: typedef BgpConfigManager::InstanceMap BgpInstanceMap; + typedef BgpConfigManager::RoutingPolicyMap BgpRoutingPolicyMap; typedef std::map IfmapInstanceMap; + typedef std::map IfmapRoutingPolicyMap; typedef std::map IfmapPeeringMap; + typedef std::map IfmapRoutingPolicyLinkMap; BgpIfmapConfigData(); ~BgpIfmapConfigData(); @@ -268,6 +349,12 @@ class BgpIfmapConfigData { BgpIfmapInstanceConfig *FindInstance(const std::string &name); const BgpIfmapInstanceConfig *FindInstance(const std::string &name) const; + // Routing Policy + BgpIfmapRoutingPolicyConfig *LocateRoutingPolicy(const std::string &name); + void DeleteRoutingPolicy(BgpIfmapRoutingPolicyConfig *rtp); + BgpIfmapRoutingPolicyConfig *FindRoutingPolicy(const std::string &name); + const BgpIfmapRoutingPolicyConfig *FindRoutingPolicy(const std::string &name) const; + BgpIfmapPeeringConfig *CreatePeering(BgpIfmapInstanceConfig *rti, IFMapNodeProxy *proxy); void DeletePeering(BgpIfmapPeeringConfig *peer); @@ -275,15 +362,28 @@ class BgpIfmapConfigData { const BgpIfmapPeeringConfig *FindPeering(const std::string &name) const; int PeeringCount() const { return peerings_.size(); } + BgpIfmapRoutingPolicyLinkConfig * + CreateRoutingPolicyLink(BgpIfmapInstanceConfig *rti, + BgpIfmapRoutingPolicyConfig *rtp, + IFMapNodeProxy *proxy); + void DeleteRoutingPolicyLink(BgpIfmapRoutingPolicyLinkConfig *ri_rp_link); + BgpIfmapRoutingPolicyLinkConfig *FindRoutingPolicyLink(const std::string &name); + const BgpIfmapRoutingPolicyLinkConfig *FindRoutingPolicyLink(const std::string &name) const; + BgpConfigManager::InstanceMapRange InstanceMapItems( const std::string &start_name = std::string()) const; + BgpConfigManager::RoutingPolicyMapRange RoutingPolicyMapItems( + const std::string &start_name = std::string()) const; const IfmapInstanceMap &instances() const { return instances_; } private: IfmapInstanceMap instances_; BgpInstanceMap instance_config_map_; + IfmapRoutingPolicyMap routing_policies_; + BgpRoutingPolicyMap routing_policy_config_map_; IfmapPeeringMap peerings_; + IfmapRoutingPolicyLinkMap ri_rp_links_; DISALLOW_COPY_AND_ASSIGN(BgpIfmapConfigData); }; @@ -321,6 +421,8 @@ class BgpIfmapConfigManager : public BgpConfigManager, virtual InstanceMapRange InstanceMapItems( const std::string &start_name = std::string()) const; + virtual RoutingPolicyMapRange RoutingPolicyMapItems( + const std::string &start_name = std::string()) const; virtual NeighborMapRange NeighborMapItems( const std::string &instance_name) const; @@ -328,6 +430,8 @@ class BgpIfmapConfigManager : public BgpConfigManager, virtual const BgpInstanceConfig *FindInstance( const std::string &name) const; + virtual const BgpRoutingPolicyConfig *FindRoutingPolicy( + const std::string &name) const; virtual const BgpProtocolConfig *GetProtocolConfig( const std::string &instance_name) const; virtual const BgpNeighborConfig *FindNeighbor( @@ -353,6 +457,8 @@ class BgpIfmapConfigManager : public BgpConfigManager, void ProcessChanges(const ChangeList &change_list); void ProcessRoutingInstance(const BgpConfigDelta &change); + void ProcessRoutingPolicyLink(const BgpConfigDelta &change); + void ProcessRoutingPolicy(const BgpConfigDelta &change); void ProcessBgpRouter(const BgpConfigDelta &change); void ProcessBgpProtocol(const BgpConfigDelta &change); void ProcessBgpPeering(const BgpConfigDelta &change); diff --git a/src/bgp/bgp_config_listener.cc b/src/bgp/bgp_config_listener.cc index c7a2a80fa3c..ede13babffb 100644 --- a/src/bgp/bgp_config_listener.cc +++ b/src/bgp/bgp_config_listener.cc @@ -51,9 +51,21 @@ void BgpConfigListener::DependencyTrackerInit() { ReactionMap rt_instance_react = map_list_of ("instance-target", list_of("self")("connection")) ("connection", list_of("self")) - ("virtual-network-routing-instance", list_of("self")); + ("virtual-network-routing-instance", list_of("self")) + ("routing-instance-routing-policy", list_of("self")); policy->insert(make_pair("routing-instance", rt_instance_react)); + ReactionMap routing_policy_assoc_react = map_list_of + ("self", list_of("routing-instance-routing-policy")) + ("routing-instance-routing-policy", list_of("routing-instance-routing-policy")); + policy->insert(make_pair("routing-instance-routing-policy", + routing_policy_assoc_react)); + + ReactionMap routing_policy_react = map_list_of + ("self", list_of("routing-instance-routing-policy")) + ("routing-instance-routing-policy", list_of("self")); + policy->insert(make_pair("routing-policy", routing_policy_react)); + ReactionMap virtual_network_react = map_list_of ("self", list_of("virtual-network-routing-instance")); policy->insert(make_pair("virtual-network", virtual_network_react)); diff --git a/src/bgp/bgp_config_parser.cc b/src/bgp/bgp_config_parser.cc index 8686fa4098c..128fab6d4d0 100644 --- a/src/bgp/bgp_config_parser.cc +++ b/src/bgp/bgp_config_parser.cc @@ -296,6 +296,29 @@ static bool ParseServiceChain(const string &instance, const xml_node &node, return true; } +static bool ParseInstanceRoutingPolicy(const string &instance, + const xml_node &node, bool add_change, + BgpConfigParser::RequestList *requests) { + + xml_attribute to = node.attribute("to"); + assert(to); + string policy_name = to.value(); + auto_ptr attr( + new autogen::RoutingPolicyType()); + assert(attr->XmlParse(node)); + if (add_change) { + MapObjectLinkAttr("routing-instance", instance, + "routing-policy", policy_name, + "routing-instance-routing-policy", attr.release(), requests); + } else { + MapObjectUnlink("routing-instance", instance, + "routing-policy", policy_name, + "routing-instance-routing-policy", requests); + } + + return true; +} + static bool ParseStaticRoute(const string &instance, const xml_node &node, bool add_change, BgpConfigParser::RequestList *requests) { @@ -465,6 +488,8 @@ bool BgpConfigParser::ParseRoutingInstance(const xml_node &parent, } else if (strcmp(node.name(), "ipv6-service-chain-info") == 0) { ParseServiceChain(instance, node, add_change, Address::INET6, requests); + } else if (strcmp(node.name(), "routing-policy") == 0) { + ParseInstanceRoutingPolicy(instance, node, add_change, requests); } else if (strcmp(node.name(), "static-route-entries") == 0) { ParseStaticRoute(instance, node, add_change, requests); } @@ -504,6 +529,28 @@ bool BgpConfigParser::ParseVirtualNetwork(const xml_node &node, return true; } +bool BgpConfigParser::ParseRoutingPolicy(const xml_node &node, + bool add_change, + RequestList *requests) const { + // policy name + string policy_name(node.attribute("name").value()); + assert(!policy_name.empty()); + + auto_ptr policy_statement( + new autogen::PolicyStatement()); + assert(policy_statement->XmlParse(node)); + + if (add_change) { + MapObjectSetProperty("routing-policy", policy_name, + "routing-policy-entries", policy_statement.release(), requests); + } else { + MapObjectClearProperty("routing-policy", policy_name, + "routing-policy-entries", requests); + } + + return true; +} + bool BgpConfigParser::ParseConfig(const xml_node &root, bool add_change, RequestList *requests) const { SessionMap sessions; @@ -524,6 +571,9 @@ bool BgpConfigParser::ParseConfig(const xml_node &root, bool add_change, if (strcmp(node.name(), "virtual-network") == 0) { ParseVirtualNetwork(node, add_change, requests); } + if (strcmp(node.name(), "routing-policy") == 0) { + ParseRoutingPolicy(node, add_change, requests); + } } if (add_change) { diff --git a/src/bgp/bgp_config_parser.h b/src/bgp/bgp_config_parser.h index d2ac2cf6c8e..2cae9ba3d27 100644 --- a/src/bgp/bgp_config_parser.h +++ b/src/bgp/bgp_config_parser.h @@ -35,6 +35,8 @@ class BgpConfigParser { RequestList *requests) const; bool ParseVirtualNetwork(const pugi::xml_node &parent, bool add_change, RequestList *requests) const; + bool ParseRoutingPolicy(const pugi::xml_node &parent, bool add_change, + RequestList *requests) const; DB *db_; DISALLOW_COPY_AND_ASSIGN(BgpConfigParser); diff --git a/src/bgp/bgp_config_yaml.cc b/src/bgp/bgp_config_yaml.cc index 8459bbcaf7f..61b310803ed 100644 --- a/src/bgp/bgp_config_yaml.cc +++ b/src/bgp/bgp_config_yaml.cc @@ -59,6 +59,7 @@ class BgpYamlConfigManager::Configuration { } virtual ~Configuration() { + STLDeleteElements(&routing_policies_); STLDeleteElements(&instances_); STLDeleteElements(&config_map_); } @@ -96,6 +97,12 @@ class BgpYamlConfigManager::Configuration { return &instances_; } + const RoutingPolicyMap &GetRoutingPolicyMap() const { + return routing_policies_; + } + RoutingPolicyMap *RoutingPolicyMapMutable() { + return &routing_policies_; + } private: BgpInstanceConfig *LocateInstance(const std::string &name) { InstanceMap::iterator loc = instances_.find(name); @@ -109,6 +116,17 @@ class BgpYamlConfigManager::Configuration { } + BgpRoutingPolicyConfig *LocateRoutingPolicy(const std::string &name) { + RoutingPolicyMap::iterator loc = routing_policies_.find(name); + if (loc != routing_policies_.end()) { + return loc->second; + } + pair result = + routing_policies_.insert( + make_pair(name, new BgpRoutingPolicyConfig(name))); + return result.first->second; + } + YamlInstanceData *LocateInstanceData(const std::string &name) { InstanceDataMap::iterator loc = config_map_.find(name); if (loc != config_map_.end()) { @@ -129,6 +147,7 @@ class BgpYamlConfigManager::Configuration { } BgpConfigManager::InstanceMap instances_; + BgpConfigManager::RoutingPolicyMap routing_policies_; InstanceDataMap config_map_; }; @@ -167,6 +186,13 @@ BgpYamlConfigManager::InstanceMapItems(const string &start_name) const { return make_pair(map.lower_bound(start_name), map.end()); } +BgpConfigManager::RoutingPolicyMapRange +BgpYamlConfigManager::RoutingPolicyMapItems( + const std::string &policy_name) const { + const BgpConfigManager::RoutingPolicyMap map = data_->GetRoutingPolicyMap(); + return make_pair(map.begin(), map.end()); +} + BgpConfigManager::NeighborMapRange BgpYamlConfigManager::NeighborMapItems( const std::string &instance_name) const { const BgpConfigManager::NeighborMap map = data_->GetNeighborMap(); diff --git a/src/bgp/bgp_factory.cc b/src/bgp/bgp_factory.cc index 19abd77d918..4b2769f46bd 100644 --- a/src/bgp/bgp_factory.cc +++ b/src/bgp/bgp_factory.cc @@ -33,6 +33,9 @@ FACTORY_STATIC_REGISTER(BgpObjectFactory, RoutingInstance, RoutingInstance); FACTORY_STATIC_REGISTER(BgpObjectFactory, RoutingInstanceMgr, RoutingInstanceMgr); +#include "bgp/routing-policy/routing_policy.h" +FACTORY_STATIC_REGISTER(BgpObjectFactory, RoutingPolicyMgr, RoutingPolicyMgr); + #include "bgp/routing-instance/rtarget_group_mgr.h" FACTORY_STATIC_REGISTER(BgpObjectFactory, RTargetGroupMgr, RTargetGroupMgr); diff --git a/src/bgp/bgp_factory.h b/src/bgp/bgp_factory.h index 78bc0686606..614e0df4fbd 100644 --- a/src/bgp/bgp_factory.h +++ b/src/bgp/bgp_factory.h @@ -37,6 +37,7 @@ class RibOut; class RibOutUpdates; class RoutingInstance; class RoutingInstanceMgr; +class RoutingPolicyMgr; class RTargetGroupMgr; class SchedulingGroup; class StateMachine; @@ -52,6 +53,7 @@ class BgpObjectFactory : public Factory { FACTORY_TYPE_N1(BgpObjectFactory, PeerRibMembershipManager, BgpServer *); FACTORY_TYPE_N1(BgpObjectFactory, RibOutUpdates, RibOut *); FACTORY_TYPE_N1(BgpObjectFactory, RoutingInstanceMgr, BgpServer *); + FACTORY_TYPE_N1(BgpObjectFactory, RoutingPolicyMgr, BgpServer *); FACTORY_TYPE_N1(BgpObjectFactory, RTargetGroupMgr, BgpServer *); FACTORY_TYPE_N1(BgpObjectFactory, StateMachine, BgpPeer *); FACTORY_TYPE_N2(BgpObjectFactory, BgpSessionManager, diff --git a/src/bgp/bgp_server.cc b/src/bgp/bgp_server.cc index ed662ad6f99..09d322b43f1 100644 --- a/src/bgp/bgp_server.cc +++ b/src/bgp/bgp_server.cc @@ -19,6 +19,7 @@ #include "bgp/routing-instance/peer_manager.h" #include "bgp/routing-instance/routepath_replicator.h" #include "bgp/routing-instance/rtarget_group_mgr.h" +#include "bgp/routing-policy/routing_policy.h" using boost::system::error_code; using process::ConnectionState; @@ -38,6 +39,8 @@ class BgpServer::ConfigUpdater { boost::bind(&ConfigUpdater::ProcessProtocolConfig, this, _1, _2); obs.neighbor = boost::bind(&ConfigUpdater::ProcessNeighborConfig, this, _1, _2); + obs.policy = + boost::bind(&ConfigUpdater::ProcessRoutingPolicyConfig, this, _1, _2); server->config_manager()->RegisterObservers(obs); } @@ -179,6 +182,16 @@ class BgpServer::ConfigUpdater { } } + void ProcessRoutingPolicyConfig(const BgpRoutingPolicyConfig *policy_config, + BgpConfigManager::EventType event) { + if (event == BgpConfigManager::CFG_ADD || + event == BgpConfigManager::CFG_CHANGE) { + return; + } else if (event == BgpConfigManager::CFG_DELETE) { + return; + } + } + void ProcessInstanceConfig(const BgpInstanceConfig *instance_config, BgpConfigManager::EventType event) { RoutingInstanceMgr *mgr = server_->routing_instance_mgr(); @@ -282,6 +295,7 @@ BgpServer::BgpServer(EventManager *evm) session_mgr_(BgpObjectFactory::Create(evm, this)), sched_mgr_(new SchedulingGroupManager), inst_mgr_(BgpObjectFactory::Create(this)), + policy_mgr_(BgpObjectFactory::Create(this)), rtarget_group_mgr_(BgpObjectFactory::Create(this)), membership_mgr_(BgpObjectFactory::Create(this)), inet_condition_listener_(new BgpConditionListener(this)), diff --git a/src/bgp/bgp_server.h b/src/bgp/bgp_server.h index a77b89f3be5..0332e92bfe7 100644 --- a/src/bgp/bgp_server.h +++ b/src/bgp/bgp_server.h @@ -41,6 +41,7 @@ class PmsiTunnelDB; class PeerRibMembershipManager; class RoutePathReplicator; class RoutingInstanceMgr; +class RoutingPolicyMgr; class RTargetGroupMgr; class SchedulingGroupManager; @@ -78,6 +79,10 @@ class BgpServer { const RoutingInstanceMgr *routing_instance_mgr() const { return inst_mgr_.get(); } + RoutingPolicyMgr *route_policy_mgr() { return policy_mgr_.get(); } + const RoutingPolicyMgr *route_policy_mgr() const { + return policy_mgr_.get(); + } RTargetGroupMgr *rtarget_group_mgr() { return rtarget_group_mgr_.get(); } const RTargetGroupMgr *rtarget_group_mgr() const { return rtarget_group_mgr_.get(); @@ -247,6 +252,7 @@ class BgpServer { BgpSessionManager *session_mgr_; boost::scoped_ptr sched_mgr_; boost::scoped_ptr inst_mgr_; + boost::scoped_ptr policy_mgr_; boost::scoped_ptr rtarget_group_mgr_; boost::scoped_ptr membership_mgr_; boost::scoped_ptr inet_condition_listener_; diff --git a/src/bgp/daemon/SConscript b/src/bgp/daemon/SConscript index fca2ddee1bc..213738e93e1 100644 --- a/src/bgp/daemon/SConscript +++ b/src/bgp/daemon/SConscript @@ -9,6 +9,7 @@ env = BuildEnv.Clone() libs = [ 'bgp', 'routing_instance', + 'routing_policy', 'extended_community', 'security_group', 'tunnel_encap', @@ -60,6 +61,7 @@ libpath = [ '../l3vpn', '../origin-vn', '../routing-instance', + '../routing-policy', '../rtarget', '../security_group', '../tunnel_encap', diff --git a/src/bgp/ermvpn/test/SConscript b/src/bgp/ermvpn/test/SConscript index 28f71e44eed..2e81cb6e1f6 100644 --- a/src/bgp/ermvpn/test/SConscript +++ b/src/bgp/ermvpn/test/SConscript @@ -25,6 +25,7 @@ env.Append(LIBPATH = env['TOP'] + '/bgp/inet6') env.Append(LIBPATH = env['TOP'] + '/bgp/inet6vpn') env.Append(LIBPATH = env['TOP'] + '/bgp/origin-vn') env.Append(LIBPATH = env['TOP'] + '/bgp/routing-instance') +env.Append(LIBPATH = env['TOP'] + '/bgp/routing-policy') env.Append(LIBPATH = env['TOP'] + '/bgp/rtarget') env.Append(LIBPATH = env['TOP'] + '/bgp/security_group') env.Append(LIBPATH = env['TOP'] + '/bgp/tunnel_encap') @@ -48,6 +49,7 @@ env.Prepend(LIBS = [ 'control_node', 'origin_vn', 'routing_instance', + 'routing_policy', 'rtarget', 'security_group', 'tunnel_encap', diff --git a/src/bgp/evpn/test/SConscript b/src/bgp/evpn/test/SConscript index 8a02780f8dd..3bf77c8516e 100644 --- a/src/bgp/evpn/test/SConscript +++ b/src/bgp/evpn/test/SConscript @@ -25,6 +25,7 @@ env.Append(LIBPATH = env['TOP'] + '/bgp/l3vpn') env.Append(LIBPATH = env['TOP'] + '/bgp/inet6vpn') env.Append(LIBPATH = env['TOP'] + '/bgp/origin-vn') env.Append(LIBPATH = env['TOP'] + '/bgp/routing-instance') +env.Append(LIBPATH = env['TOP'] + '/bgp/routing-policy') env.Append(LIBPATH = env['TOP'] + '/bgp/rtarget') env.Append(LIBPATH = env['TOP'] + '/bgp/security_group') env.Append(LIBPATH = env['TOP'] + '/bgp/tunnel_encap') @@ -49,6 +50,7 @@ env.Prepend(LIBS = [ 'peer_sandesh', 'origin_vn', 'routing_instance', + 'routing_policy', 'rtarget', 'security_group', 'tunnel_encap', diff --git a/src/bgp/inet/test/SConscript b/src/bgp/inet/test/SConscript index 92e5999a6ed..f59edfc26ed 100644 --- a/src/bgp/inet/test/SConscript +++ b/src/bgp/inet/test/SConscript @@ -26,6 +26,7 @@ env.Append(LIBPATH = env['TOP'] + '/bgp/test') env.Append(LIBPATH = env['TOP'] + '/bgp/l3vpn') env.Append(LIBPATH = env['TOP'] + '/bgp/origin-vn') env.Append(LIBPATH = env['TOP'] + '/bgp/routing-instance') +env.Append(LIBPATH = env['TOP'] + '/bgp/routing-policy') env.Append(LIBPATH = env['TOP'] + '/bgp/rtarget') env.Append(LIBPATH = env['TOP'] + '/bgp/security_group') env.Append(LIBPATH = env['TOP'] + '/bgp/tunnel_encap') @@ -49,6 +50,7 @@ env.Prepend(LIBS = [ 'control_node', 'origin_vn', 'routing_instance', + 'routing_policy', 'rtarget', 'security_group', 'tunnel_encap', diff --git a/src/bgp/inet6/test/SConscript b/src/bgp/inet6/test/SConscript index 1f52e23d5ee..445b447d27b 100644 --- a/src/bgp/inet6/test/SConscript +++ b/src/bgp/inet6/test/SConscript @@ -26,6 +26,7 @@ env.Append(LIBPATH = env['TOP'] + '/bgp/test') env.Append(LIBPATH = env['TOP'] + '/bgp/l3vpn') env.Append(LIBPATH = env['TOP'] + '/bgp/origin-vn') env.Append(LIBPATH = env['TOP'] + '/bgp/routing-instance') +env.Append(LIBPATH = env['TOP'] + '/bgp/routing-policy') env.Append(LIBPATH = env['TOP'] + '/bgp/rtarget') env.Append(LIBPATH = env['TOP'] + '/bgp/security_group') env.Append(LIBPATH = env['TOP'] + '/bgp/tunnel_encap') @@ -49,6 +50,7 @@ env.Prepend(LIBS = [ 'control_node', 'origin_vn', 'routing_instance', + 'routing_policy', 'rtarget', 'security_group', 'tunnel_encap', diff --git a/src/bgp/inet6vpn/test/SConscript b/src/bgp/inet6vpn/test/SConscript index f68c9ea8937..da113ea79ed 100644 --- a/src/bgp/inet6vpn/test/SConscript +++ b/src/bgp/inet6vpn/test/SConscript @@ -25,6 +25,7 @@ env.Append(LIBPATH = env['TOP'] + '/bgp/inet6') env.Append(LIBPATH = env['TOP'] + '/bgp/inet6vpn') env.Append(LIBPATH = env['TOP'] + '/bgp/origin-vn') env.Append(LIBPATH = env['TOP'] + '/bgp/routing-instance') +env.Append(LIBPATH = env['TOP'] + '/bgp/routing-policy') env.Append(LIBPATH = env['TOP'] + '/bgp/rtarget') env.Append(LIBPATH = env['TOP'] + '/bgp/security_group') env.Append(LIBPATH = env['TOP'] + '/bgp/tunnel_encap') @@ -48,6 +49,7 @@ env.Prepend(LIBS = [ 'control_node', 'origin_vn', 'routing_instance', + 'routing_policy', 'rtarget', 'security_group', 'tunnel_encap', diff --git a/src/bgp/l3vpn/test/SConscript b/src/bgp/l3vpn/test/SConscript index e06b98042bf..df4788d6fa0 100644 --- a/src/bgp/l3vpn/test/SConscript +++ b/src/bgp/l3vpn/test/SConscript @@ -27,6 +27,7 @@ env.Append(LIBPATH = env['TOP'] + '/bgp/l3vpn') env.Append(LIBPATH = env['TOP'] + '/bgp/inet6vpn') env.Append(LIBPATH = env['TOP'] + '/bgp/origin-vn') env.Append(LIBPATH = env['TOP'] + '/bgp/routing-instance') +env.Append(LIBPATH = env['TOP'] + '/bgp/routing-policy') env.Append(LIBPATH = env['TOP'] + '/bgp/rtarget') env.Append(LIBPATH = env['TOP'] + '/bgp/security_group') env.Append(LIBPATH = env['TOP'] + '/bgp/tunnel_encap') @@ -51,6 +52,7 @@ env.Prepend(LIBS = [ 'control_node', 'origin_vn', 'routing_instance', + 'routing_policy', 'rtarget', 'security_group', 'tunnel_encap', diff --git a/src/bgp/routing-policy/SConscript b/src/bgp/routing-policy/SConscript new file mode 100644 index 00000000000..d864ca8d89b --- /dev/null +++ b/src/bgp/routing-policy/SConscript @@ -0,0 +1,16 @@ +# +# Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. +# + +# -*- mode: python; -*- + +Import('BuildEnv') + +env = BuildEnv.Clone() +env.Append(CPPPATH = env['TOP']) +env.Append(CPPPATH = [env['TOP'] + '/bgp']) +env.Append(CPPPATH = [env['TOP'] + '/db']) +env.Append(CPPPATH = [env['TOP'] + '/io']) + +librouting_policy = env.Library('routing_policy', ['routing_policy.cc']) + diff --git a/src/bgp/routing-policy/routing_policy.cc b/src/bgp/routing-policy/routing_policy.cc new file mode 100644 index 00000000000..a452cdb6b6d --- /dev/null +++ b/src/bgp/routing-policy/routing_policy.cc @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ + +#include "bgp/routing-policy/routing_policy.h" + + +RoutingPolicyMgr::RoutingPolicyMgr(BgpServer *server) + : server_(server), + trace_buf_(SandeshTraceBufferCreate("RoutingPolicyMgr", 500)) { +} + +RoutingPolicyMgr::~RoutingPolicyMgr() { +} + + diff --git a/src/bgp/routing-policy/routing_policy.h b/src/bgp/routing-policy/routing_policy.h new file mode 100644 index 00000000000..57d3932c148 --- /dev/null +++ b/src/bgp/routing-policy/routing_policy.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_BGP_ROUTING_POLICY_ROUTING_POLICY_H_ +#define SRC_BGP_ROUTING_POLICY_ROUTING_POLICY_H_ + +#include + +class BgpServer; + +class RoutingPolicyMgr { +public: + RoutingPolicyMgr(BgpServer *server); + virtual ~RoutingPolicyMgr(); + SandeshTraceBufferPtr trace_buffer() const { return trace_buf_; } + +private: + BgpServer *server() { return server_; } + const BgpServer *server() const { return server_; }; + BgpServer *server_; + SandeshTraceBufferPtr trace_buf_; +}; +#endif // SRC_BGP_ROUTING_POLICY_ROUTING_POLICY_H_ + + diff --git a/src/bgp/rtarget/test/SConscript b/src/bgp/rtarget/test/SConscript index f0e34288c3f..f9c1bd43abe 100644 --- a/src/bgp/rtarget/test/SConscript +++ b/src/bgp/rtarget/test/SConscript @@ -20,6 +20,7 @@ env.Append(LIBPATH = [env['TOP'] + '/base', env['TOP'] + '/base/test', env['TOP'] + '/bgp/inet', env['TOP'] + '/bgp/l3vpn', env['TOP'] + '/bgp/inet6', env['TOP'] + '/bgp/inet6vpn', env['TOP'] + '/bgp/origin-vn', env['TOP'] + '/bgp/routing-instance', + env['TOP'] + '/bgp/routing-policy', env['TOP'] + '/bgp/rtarget', env['TOP'] + '/bgp/security_group', env['TOP'] + '/bgp/test', env['TOP'] + '/bgp/tunnel_encap', env['TOP'] + '/control-node', env['TOP'] + '/control-node/test', @@ -42,7 +43,7 @@ env.Prepend(LIBS = ['control_test', 'bgptest', 'bgp', 'peer_sandesh', env.Append(LIBS = ['bgp_ermvpn', 'bgp_evpn']) env.Append(LIBS = ['bgp_inet', 'bgp_l3vpn']) env.Append(LIBS = ['bgp_inet6', 'bgp_inet6vpn']) -env.Append(LIBS = ['routing_instance', 'rtarget', 'route', 'net']) +env.Append(LIBS = ['routing_instance', 'rtarget', 'route', 'routing_polcy', 'net']) env.Append(LIBS = ['extended_community', 'origin_vn', 'security_group', 'tunnel_encap']) env.Append(LIBS = ['xmpp', 'xmpp_unicast', 'xmpp_multicast', 'xmpp_enet', 'xml', 'pugixml', diff --git a/src/bgp/test/SConscript b/src/bgp/test/SConscript index 3e8a75fec33..f35b130d36d 100644 --- a/src/bgp/test/SConscript +++ b/src/bgp/test/SConscript @@ -33,6 +33,7 @@ env.Append(LIBPATH = ['#/' + Dir('..').path, '../origin-vn', '../rtarget', '../routing-instance', + '../routing-policy', '../../route', '../security_group', '../tunnel_encap', @@ -118,7 +119,7 @@ env.Append(LIBS = [ 'rtarget', ]) -env.Append(LIBS = ['route', 'routing_instance', 'net']) +env.Append(LIBS = ['route', 'routing_instance', 'routing_policy', 'net']) env.Append(LIBS = ['extended_community', 'origin_vn', 'security_group', 'tunnel_encap']) env.Append(LIBS = ['xmpp_unicast', 'xmpp_multicast', 'xmpp_enet', diff --git a/src/bgp/test/bgp_config_mock.cc b/src/bgp/test/bgp_config_mock.cc index eeca77a30ec..593a796c928 100644 --- a/src/bgp/test/bgp_config_mock.cc +++ b/src/bgp/test/bgp_config_mock.cc @@ -26,6 +26,12 @@ class BgpMockConfigManager : public BgpConfigManager { return make_pair(instance_map_.lower_bound(name), instance_map_.end()); } + virtual RoutingPolicyMapRange RoutingPolicyMapItems( + const std::string &name = std::string()) const { + return make_pair(routing_policy_map_.lower_bound(name), + routing_policy_map_.end()); + } + virtual NeighborMapRange NeighborMapItems( const std::string &instance_name) const { return make_pair(neighbor_map_.begin(), neighbor_map_.end()); @@ -40,6 +46,11 @@ class BgpMockConfigManager : public BgpConfigManager { return NULL; } + virtual const BgpRoutingPolicyConfig *FindRoutingPolicy( + const std::string &name) const { + return NULL; + } + virtual const BgpProtocolConfig *GetProtocolConfig( const std::string &instance_name) const { return NULL; @@ -52,6 +63,7 @@ class BgpMockConfigManager : public BgpConfigManager { private: std::string localname_; + RoutingPolicyMap routing_policy_map_; InstanceMap instance_map_; NeighborMap neighbor_map_; }; diff --git a/src/bgp/test/bgp_config_test.cc b/src/bgp/test/bgp_config_test.cc index 63af4779ce7..05cebb736f2 100644 --- a/src/bgp/test/bgp_config_test.cc +++ b/src/bgp/test/bgp_config_test.cc @@ -1230,6 +1230,44 @@ TEST_F(BgpConfigTest, AddressFamilies3) { TASK_UTIL_EXPECT_EQ(0, db_graph_.vertex_count()); } +TEST_F(BgpConfigTest, RoutePolicy_0) { + string content = FileRead("controller/src/bgp/testdata/routing_policy_0.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::replace_all(content, "", ""); + boost::replace_all(content, "", ""); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + TASK_UTIL_EXPECT_EQ(0, db_graph_.vertex_count()); +} + +TEST_F(BgpConfigTest, RoutePolicy_1) { + string content = FileRead("controller/src/bgp/testdata/routing_policy_1.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::replace_all(content, "", ""); + boost::replace_all(content, "", ""); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + TASK_UTIL_EXPECT_EQ(0, db_graph_.vertex_count()); +} + +TEST_F(BgpConfigTest, RoutePolicy_2) { + string content = FileRead("controller/src/bgp/testdata/routing_policy_2.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::replace_all(content, "", ""); + boost::replace_all(content, "", ""); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + TASK_UTIL_EXPECT_EQ(0, db_graph_.vertex_count()); +} int main(int argc, char **argv) { bgp_log_test::init(); ControlNode::SetDefaultSchedulingPolicy(); diff --git a/src/bgp/testdata/routing_policy_0.xml b/src/bgp/testdata/routing_policy_0.xml new file mode 100644 index 00000000000..b69dca4b669 --- /dev/null +++ b/src/bgp/testdata/routing_policy_0.xml @@ -0,0 +1,30 @@ + + + + + + 23:13 + + + + 102 + + accept + + + + + 11:13 + + + reject + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_1.xml b/src/bgp/testdata/routing_policy_1.xml new file mode 100644 index 00000000000..487ead35580 --- /dev/null +++ b/src/bgp/testdata/routing_policy_1.xml @@ -0,0 +1,36 @@ + + + + + + 23:13 + + + + 102 + + accept + + + + + + + 23:11 + + + reject + + + + + + + 1.0 + + + 1.1 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_2.xml b/src/bgp/testdata/routing_policy_2.xml new file mode 100644 index 00000000000..04cccda11e9 --- /dev/null +++ b/src/bgp/testdata/routing_policy_2.xml @@ -0,0 +1,53 @@ + + + + + + + 3.1.0.0/16 + longer + + + + + 102 + + accept + + + + + + 3.1.1.1 + exact + + + + reject + + + + + + 1/8 + orlonger + + + + + + + 11:44 + + + + + + + + + 1.0 + + target:1:103 + + diff --git a/src/control-node/SConscript b/src/control-node/SConscript index 173704b9f21..15e1a70b1a1 100644 --- a/src/control-node/SConscript +++ b/src/control-node/SConscript @@ -76,6 +76,7 @@ env.Prepend(LIBS=['bgp', 'peer_sandesh', 'origin_vn', 'routing_instance', + 'routing_policy', 'rtarget', 'security_group', 'tunnel_encap', @@ -121,6 +122,7 @@ libs = MapBuildDir(['base', 'bgp/l3vpn', 'bgp/origin-vn', 'bgp/routing-instance', + 'bgp/routing-policy', 'bgp/rtarget', 'bgp/security_group', 'bgp/tunnel_encap', @@ -180,6 +182,7 @@ buildinfo_dep_libs = ['../bgp/libbgp.a', '../schema/libbgp_schema.a', '../schema/libxmpp_unicast.a', '../schema/libxmpp_multicast.a', '../schema/libxmpp_enet.a', '../control-node/libcontrol_node.a', '../bgp/routing-instance/librouting_instance.a', + '../bgp/routing-policy/librouting_policy.a', '../bgp/origin-vn/liborigin_vn.a', '../bgp/extended-community/libextended_community.a', '../bgp/rtarget/librtarget.a', '../bgp/security_group/libsecurity_group.a', '../schema/libifmap_vnc.a',