diff --git a/src/bgp/bgp_common.h b/src/bgp/bgp_common.h index ccf139b7197..09c2795566d 100644 --- a/src/bgp/bgp_common.h +++ b/src/bgp/bgp_common.h @@ -4,8 +4,11 @@ #ifndef ctrlplane_bgp_common_h #define ctrlplane_bgp_common_h - +#include typedef uint16_t as_t; typedef uint32_t as4_t; +class RoutingPolicy; +typedef boost::intrusive_ptr RoutingPolicyPtr; + #endif diff --git a/src/bgp/bgp_config.h b/src/bgp/bgp_config.h index 3c9d243bb30..c57b74f734b 100644 --- a/src/bgp/bgp_config.h +++ b/src/bgp/bgp_config.h @@ -288,7 +288,7 @@ struct PrefixMatch { std::string prefix_match_type; }; -struct RoutingPolicyMatch { +struct RoutingPolicyMatchConfig { std::string community_match; PrefixMatch prefix_match; }; @@ -300,7 +300,7 @@ struct ActionUpdate { uint32_t local_pref; }; -struct RoutingPolicyAction { +struct RoutingPolicyActionConfig { enum ActionType { ACCEPT, REJECT, @@ -311,8 +311,8 @@ struct RoutingPolicyAction { }; struct RoutingPolicyTerm { - RoutingPolicyMatch match; - RoutingPolicyAction action; + RoutingPolicyMatchConfig match; + RoutingPolicyActionConfig action; }; // Route Policy configuration. @@ -338,7 +338,7 @@ class BgpRoutingPolicyConfig { }; struct RoutingPolicyAttachInfo { - std::string sequence_; + double sequence_; std::string routing_policy_; }; diff --git a/src/bgp/bgp_config_ifmap.cc b/src/bgp/bgp_config_ifmap.cc index 1d24e06b656..ee1f954d02f 100644 --- a/src/bgp/bgp_config_ifmap.cc +++ b/src/bgp/bgp_config_ifmap.cc @@ -6,6 +6,7 @@ #include +#include "base/string_util.h" #include "base/task_annotations.h" #include "bgp/bgp_config_listener.h" #include "bgp/bgp_log.h" @@ -713,21 +714,26 @@ static void GetConnectionExportTargets(DBGraph *graph, IFMapNode *src_node, // 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) { +static bool GetRoutingInstanceRoutingPolicy(DBGraph *graph, IFMapNode *node, + RoutingPolicyAttachInfo *ri_rp_link) { std::string sequence; const autogen::RoutingInstanceRoutingPolicy *policy = static_cast(node->GetObject()); const autogen::RoutingPolicyType &attach_info = policy->data(); - routing_policy->sequence_ = attach_info.sequence; + + if (!stringToInteger(attach_info.sequence, ri_rp_link->sequence_)) { + return false; + } + 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; + ri_rp_link->routing_policy_ = adj->name(); + return true; } } + return false; } // @@ -904,6 +910,11 @@ void BgpIfmapConfigManager::ProcessRoutingPolicyLink(const BgpConfigDelta &delta ri_rp_link->Update(this, ri_rp_link_cfg); } + +static bool CompareRoutingPolicyOrder(const RoutingPolicyAttachInfo &lhs, + const RoutingPolicyAttachInfo &rhs) { + return (lhs.sequence_ < rhs.sequence_); +} // // Update BgpIfmapInstanceConfig based on a new autogen::RoutingInstance object. // @@ -948,8 +959,9 @@ void BgpIfmapInstanceConfig::Update(BgpIfmapConfigManager *manager, } 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); + if (GetRoutingInstanceRoutingPolicy(graph, adj, &policy_info)) { + policy_list.push_back(policy_info); + } } else if (strcmp(adj->table()->Typename(), "connection") == 0) { vector target_list; GetConnectionExportTargets(graph, node, name_, adj, &target_list); @@ -967,6 +979,8 @@ void BgpIfmapInstanceConfig::Update(BgpIfmapConfigManager *manager, data_.set_import_list(import_list); data_.set_export_list(export_list); + + std::sort(policy_list.begin(), policy_list.end(), CompareRoutingPolicyOrder); data_.swap_routing_policy_list(&policy_list); if (config) { @@ -1525,11 +1539,11 @@ static void BuildPolicyTerm(autogen::PolicyTerm cfg_term, term->action.update.community_set.push_back(community); } term->action.update.local_pref = cfg_term.then.update.local_pref; - term->action.action = RoutingPolicyAction::ACCEPT; + term->action.action = RoutingPolicyActionConfig::NEXT_TERM; 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; + term->action.action = RoutingPolicyActionConfig::REJECT; + } else if (strcmp(cfg_term.then.action.c_str(), "accept") == 0) { + term->action.action = RoutingPolicyActionConfig::ACCEPT; } } diff --git a/src/bgp/bgp_config_listener.cc b/src/bgp/bgp_config_listener.cc index df36a299b78..6c98e728c1c 100644 --- a/src/bgp/bgp_config_listener.cc +++ b/src/bgp/bgp_config_listener.cc @@ -62,7 +62,8 @@ void BgpConfigListener::DependencyTrackerInit() { 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")); + ("routing-instance-routing-policy", + list_of("routing-instance-routing-policy")); policy->insert(make_pair("routing-instance-routing-policy", routing_policy_assoc_react)); diff --git a/src/bgp/bgp_factory.cc b/src/bgp/bgp_factory.cc index 4b2769f46bd..aee2bfe4cab 100644 --- a/src/bgp/bgp_factory.cc +++ b/src/bgp/bgp_factory.cc @@ -34,6 +34,7 @@ FACTORY_STATIC_REGISTER(BgpObjectFactory, RoutingInstanceMgr, RoutingInstanceMgr); #include "bgp/routing-policy/routing_policy.h" +FACTORY_STATIC_REGISTER(BgpObjectFactory, RoutingPolicy, RoutingPolicy); FACTORY_STATIC_REGISTER(BgpObjectFactory, RoutingPolicyMgr, RoutingPolicyMgr); #include "bgp/routing-instance/rtarget_group_mgr.h" diff --git a/src/bgp/bgp_factory.h b/src/bgp/bgp_factory.h index 614e0df4fbd..89e8419b07b 100644 --- a/src/bgp/bgp_factory.h +++ b/src/bgp/bgp_factory.h @@ -16,6 +16,7 @@ class BgpConfigListener; class BgpConfigManager; class BgpExport; class BgpInstanceConfig; +class BgpRoutingPolicyConfig; class BgpMessageBuilder; class BgpNeighborConfig; class BgpPeer; @@ -37,6 +38,7 @@ class RibOut; class RibOutUpdates; class RoutingInstance; class RoutingInstanceMgr; +class RoutingPolicy; class RoutingPolicyMgr; class RTargetGroupMgr; class SchedulingGroup; @@ -63,6 +65,9 @@ class BgpObjectFactory : public Factory { FACTORY_TYPE_N4(BgpObjectFactory, RoutingInstance, std::string, BgpServer *, RoutingInstanceMgr *, const BgpInstanceConfig *); + FACTORY_TYPE_N4(BgpObjectFactory, RoutingPolicy, + std::string, BgpServer *, RoutingPolicyMgr *, + const BgpRoutingPolicyConfig *); FACTORY_TYPE_N0(BgpObjectFactory, BgpMessageBuilder); FACTORY_TYPE_N0(BgpObjectFactory, BgpXmppMessageBuilder); diff --git a/src/bgp/bgp_path.h b/src/bgp/bgp_path.h index 8f5be3fb8ed..6087ae49a0b 100644 --- a/src/bgp/bgp_path.h +++ b/src/bgp/bgp_path.h @@ -24,6 +24,7 @@ class BgpPath : public Path { NoTunnelEncap = 1 << 3, OriginatorIdLooped = 1 << 4, ResolveNexthop = 1 << 5, + RoutingPolicyReject = 1 << 6, }; // Ordered in the ascending order of path preference @@ -37,7 +38,8 @@ class BgpPath : public Path { }; static const uint32_t INFEASIBLE_MASK = (AsPathLooped | - NoNeighborAs | NoTunnelEncap | OriginatorIdLooped | ResolveNexthop); + NoNeighborAs | NoTunnelEncap | OriginatorIdLooped | ResolveNexthop | + RoutingPolicyReject); static std::string PathIdString(uint32_t path_id); static std::string PathSourceString(PathSource source); @@ -80,10 +82,19 @@ class BgpPath : public Path { peer_->UpdatePrimaryPathCount(count); } + void SetAttr(const BgpAttrPtr attr, const BgpAttrPtr original_attr) { + attr_ = attr; + original_attr_ = original_attr; + } + const BgpAttr *GetAttr() const { return attr_.get(); } + const BgpAttr *GetOriginalPathAttr() const { + return original_attr_.get(); + } + uint32_t GetLabel() const { return label_; } @@ -109,6 +120,16 @@ class BgpPath : public Path { return ((flags_ & Stale) != 0); } + // Mark a path as rejected by Routing policy + void SetPolicyReject() { + flags_ |= RoutingPolicyReject; + } + + // Reset a path as active from Routing Policy + void ResetPolicyReject() { + flags_ &= ~RoutingPolicyReject; + } + // Mark a path as stale void SetStale() { flags_ |= Stale; @@ -133,7 +154,11 @@ class BgpPath : public Path { const IPeer *peer_; const uint32_t path_id_; const PathSource source_; - const BgpAttrPtr attr_; + // Attribute for the BgpPath. If routing policy updates the path attribute, + // this member contains the attribute after policy update + BgpAttrPtr attr_; + // Original path attribute before applying routing policy + BgpAttrPtr original_attr_; uint32_t flags_; uint32_t label_; }; diff --git a/src/bgp/bgp_route.cc b/src/bgp/bgp_route.cc index ff6506564d6..16eaba744fc 100644 --- a/src/bgp/bgp_route.cc +++ b/src/bgp/bgp_route.cc @@ -43,12 +43,16 @@ void BgpRoute::InsertPath(BgpPath *path) { assert(!IsDeleted()); const Path *prev_front = front(); + BgpTable *table = static_cast(get_table()); + if (table) { + RoutingInstance *rtinstance = table->routing_instance(); + rtinstance->ProcessRoutingPolicy(this, path); + } insert(path); Sort(&BgpTable::PathSelection, prev_front); // Update counters. - BgpTable *table = static_cast(get_table()); if (table) table->UpdatePathCount(path, +1); path->UpdatePeerRefCount(+1); } diff --git a/src/bgp/bgp_server.cc b/src/bgp/bgp_server.cc index e936daae6dd..a5f1ae871e8 100644 --- a/src/bgp/bgp_server.cc +++ b/src/bgp/bgp_server.cc @@ -189,12 +189,14 @@ class BgpServer::ConfigUpdater { } void ProcessRoutingPolicyConfig(const BgpRoutingPolicyConfig *policy_config, - BgpConfigManager::EventType event) { - if (event == BgpConfigManager::CFG_ADD || - event == BgpConfigManager::CFG_CHANGE) { - return; + BgpConfigManager::EventType event) { + RoutingPolicyMgr *mgr = server_->routing_policy_mgr(); + if (event == BgpConfigManager::CFG_ADD) { + mgr->CreateRoutingPolicy(policy_config); + } else if (event == BgpConfigManager::CFG_CHANGE) { + mgr->UpdateRoutingPolicy(policy_config); } else if (event == BgpConfigManager::CFG_DELETE) { - return; + mgr->DeleteRoutingPolicy(policy_config->name()); } } diff --git a/src/bgp/bgp_server.h b/src/bgp/bgp_server.h index 4f293fc580a..8fd2aab5553 100644 --- a/src/bgp/bgp_server.h +++ b/src/bgp/bgp_server.h @@ -85,8 +85,8 @@ 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 { + RoutingPolicyMgr *routing_policy_mgr() { return policy_mgr_.get(); } + const RoutingPolicyMgr *routing_policy_mgr() const { return policy_mgr_.get(); } RTargetGroupMgr *rtarget_group_mgr() { return rtarget_group_mgr_.get(); } diff --git a/src/bgp/community.cc b/src/bgp/community.cc index db30bc4d2d5..b694bd60ebf 100644 --- a/src/bgp/community.cc +++ b/src/bgp/community.cc @@ -64,6 +64,30 @@ void Community::Append(uint32_t value) { sort(communities_.begin(), communities_.end()); } +void Community::Append(const std::vector &communities) { + BOOST_FOREACH(uint32_t community, communities) { + communities_.push_back(community); + } + sort(communities_.begin(), communities_.end()); + vector::iterator it = + unique(communities_.begin(), communities_.end()); + communities_.erase(it, communities_.end()); +} + +void Community::Set(const std::vector &communities) { + communities_.clear(); + BOOST_FOREACH(uint32_t community, communities) { + communities_.push_back(community); + } +} + +void Community::Remove(const std::vector &communities) { + BOOST_FOREACH(uint32_t community, communities) { + communities_.erase( + std::remove(communities_.begin(), communities_.end(), community), + communities_.end()); + } +} void Community::Remove() { comm_db_->Delete(this); } @@ -99,6 +123,45 @@ CommunityPtr CommunityDB::AppendAndLocate(const Community *src, return Locate(clone); } +CommunityPtr CommunityDB::AppendAndLocate(const Community *src, + const std::vector &value) { + Community *clone; + if (src) { + clone = new Community(*src); + } else { + clone = new Community(this); + } + + clone->Append(value); + return Locate(clone); +} + +CommunityPtr CommunityDB::SetAndLocate(const Community *src, + const std::vector &value) { + Community *clone; + if (src) { + clone = new Community(*src); + } else { + clone = new Community(this); + } + + clone->Set(value); + return Locate(clone); +} + +CommunityPtr CommunityDB::RemoveAndLocate(const Community *src, + const std::vector &value) { + Community *clone; + if (src) { + clone = new Community(*src); + } else { + clone = new Community(this); + } + + clone->Remove(value); + return Locate(clone); +} + string ExtCommunitySpec::ToString() const { char repr[80]; snprintf(repr, sizeof(repr), "ExtCommunity :%d", diff --git a/src/bgp/community.h b/src/bgp/community.h index 8199648fde9..6975b326e28 100644 --- a/src/bgp/community.h +++ b/src/bgp/community.h @@ -55,6 +55,9 @@ class Community { virtual ~Community() { } void Append(uint32_t value); + void Append(const std::vector &communities); + void Set(const std::vector &communities); + void Remove(const std::vector &communities); virtual void Remove(); int CompareTo(const Community &rhs) const; bool ContainsValue(uint32_t value) const; @@ -113,6 +116,12 @@ class CommunityDB : public BgpPathAttributeDB &value); + CommunityPtr SetAndLocate(const Community *src, + const std::vector &value); + CommunityPtr RemoveAndLocate(const Community *src, + const std::vector &value); private: }; diff --git a/src/bgp/routing-instance/routing_instance.cc b/src/bgp/routing-instance/routing_instance.cc index 1060ffed5ba..db06a01ec36 100644 --- a/src/bgp/routing-instance/routing_instance.cc +++ b/src/bgp/routing-instance/routing_instance.cc @@ -16,6 +16,7 @@ #include "bgp/routing-instance/peer_manager.h" #include "bgp/routing-instance/routepath_replicator.h" #include "bgp/routing-instance/routing_instance_log.h" +#include "bgp/routing-policy/routing_policy.h" #include "bgp/routing-instance/rtarget_group_mgr.h" #include "bgp/rtarget/rtarget_route.h" @@ -486,6 +487,25 @@ RoutingInstance::RoutingInstance(string name, BgpServer *server, RoutingInstance::~RoutingInstance() { } +void RoutingInstance::AddRoutingPolicy(RoutingPolicyPtr policy) { + routing_policies_.push_back(policy); +} + +void RoutingInstance::ProcessRoutingPolicyConfig() { + BOOST_FOREACH(RoutingPolicyAttachInfo info, + config_->routing_policy_list()) { + RoutingPolicyMgr *policy_mgr = server()->routing_policy_mgr(); + RoutingPolicy *policy = + policy_mgr->GetRoutingPolicy(info.routing_policy_); + if (policy) { + AddRoutingPolicy(policy); + } + } +} + +void RoutingInstance::UpdateRoutingPolicyConfig() { +} + void RoutingInstance::ProcessServiceChainConfig() { vector families = list_of(Address::INET)(Address::INET6); BOOST_FOREACH(Address::Family family, families) { @@ -590,6 +610,7 @@ void RoutingInstance::ProcessConfig() { ProcessServiceChainConfig(); ProcessStaticRouteConfig(); + ProcessRoutingPolicyConfig(); } void RoutingInstance::UpdateConfig(const BgpInstanceConfig *cfg) { @@ -668,6 +689,7 @@ void RoutingInstance::UpdateConfig(const BgpInstanceConfig *cfg) { ProcessServiceChainConfig(); UpdateStaticRouteConfig(); + UpdateRoutingPolicyConfig(); } void RoutingInstance::ClearConfig() { @@ -1077,3 +1099,22 @@ bool RoutingInstance::HasExportTarget(const ExtCommunity *extcomm) const { return false; } + +bool RoutingInstance::ProcessRoutingPolicy(const BgpRoute *route, + BgpPath *path) const { + const RoutingPolicyMgr *policy_mgr = server()->routing_policy_mgr(); + BgpAttr *out_attr = new BgpAttr(*(path->GetAttr())); + BOOST_FOREACH(RoutingPolicyPtr policy, routing_policies()) { + RoutingPolicy::PolicyResult result = + policy_mgr->ApplyPolicy(policy.get(), route, out_attr); + if (result.first) { + if (!result.second) path->SetPolicyReject(); + BgpAttrPtr modified_attr = server_->attr_db()->Locate(out_attr); + path->SetAttr(modified_attr, path->GetAttr()); + return result.second; + } + } + BgpAttrPtr modified_attr = server_->attr_db()->Locate(out_attr); + path->SetAttr(modified_attr, path->GetAttr()); + return true; +} diff --git a/src/bgp/routing-instance/routing_instance.h b/src/bgp/routing-instance/routing_instance.h index 37883efd53a..0aa0ad63a38 100644 --- a/src/bgp/routing-instance/routing_instance.h +++ b/src/bgp/routing-instance/routing_instance.h @@ -27,8 +27,11 @@ #include "net/address.h" class DBTable; +class BgpAttr; class BgpInstanceConfig; class BgpNeighborConfig; +class BgpPath; +class BgpRoute; class BgpServer; class BgpTable; class IStaticRouteMgr; @@ -45,6 +48,7 @@ class RoutingInstance { public: typedef std::set RouteTargetList; typedef std::map RouteTableList; + typedef std::vector RoutingPolicyList; RoutingInstance(std::string name, BgpServer *server, RoutingInstanceMgr *mgr, @@ -54,6 +58,8 @@ class RoutingInstance { RouteTableList &GetTables() { return vrf_tables_; } const RouteTableList &GetTables() const { return vrf_tables_; } + void ProcessRoutingPolicyConfig(); + void UpdateRoutingPolicyConfig(); void ProcessServiceChainConfig(); void ProcessStaticRouteConfig(); void UpdateStaticRouteConfig(); @@ -129,6 +135,15 @@ class RoutingInstance { PeerManager *peer_manager() { return peer_manager_.get(); } const PeerManager *peer_manager() const { return peer_manager_.get(); } + RoutingPolicyList &routing_policies() { return routing_policies_; } + const RoutingPolicyList &routing_policies() const { + return routing_policies_; + } + + void AddRoutingPolicy(RoutingPolicyPtr policy); + + bool ProcessRoutingPolicy(const BgpRoute *route, BgpPath *path) const; + private: friend class RoutingInstanceMgr; class DeleteActor; @@ -173,6 +188,7 @@ class RoutingInstance { boost::scoped_ptr inet_static_route_mgr_; boost::scoped_ptr inet6_static_route_mgr_; boost::scoped_ptr peer_manager_; + RoutingPolicyList routing_policies_; }; diff --git a/src/bgp/routing-policy/SConscript b/src/bgp/routing-policy/SConscript index d864ca8d89b..18c30d33205 100644 --- a/src/bgp/routing-policy/SConscript +++ b/src/bgp/routing-policy/SConscript @@ -12,5 +12,8 @@ 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']) +librouting_policy = env.Library('routing_policy', + ['routing_policy.cc', + 'routing_policy_action.cc', + 'routing_policy_match.cc']) diff --git a/src/bgp/routing-policy/routing_policy.cc b/src/bgp/routing-policy/routing_policy.cc index a452cdb6b6d..80f12e4c3f1 100644 --- a/src/bgp/routing-policy/routing_policy.cc +++ b/src/bgp/routing-policy/routing_policy.cc @@ -4,13 +4,357 @@ #include "bgp/routing-policy/routing_policy.h" +#include +#include -RoutingPolicyMgr::RoutingPolicyMgr(BgpServer *server) - : server_(server), - trace_buf_(SandeshTraceBufferCreate("RoutingPolicyMgr", 500)) { +#include "base/task_annotations.h" +#include "bgp/bgp_config.h" +#include "bgp/bgp_factory.h" +#include "bgp/bgp_server.h" +#include "bgp/routing-policy/routing_policy_action.h" +#include "bgp/routing-policy/routing_policy_match.h" + + +class RoutingPolicyMgr::DeleteActor : public LifetimeActor { +public: + explicit DeleteActor(RoutingPolicyMgr *manager) + : LifetimeActor(manager->server_->lifetime_manager()), + manager_(manager) { + } + virtual bool MayDelete() const { + return true; + } + virtual void Shutdown() { + } + virtual void Destroy() { + // memory is deallocated by BgpServer scoped_ptr. + manager_->server_delete_ref_.Reset(NULL); + } + +private: + RoutingPolicyMgr *manager_; +}; + +RoutingPolicyMgr::RoutingPolicyMgr(BgpServer *server) : + server_(server), + deleter_(new DeleteActor(this)), + server_delete_ref_(this, server->deleter()), + trace_buf_(SandeshTraceBufferCreate("RoutingPolicyMgr", 500)) { } RoutingPolicyMgr::~RoutingPolicyMgr() { } +void RoutingPolicyMgr::ManagedDelete() { + deleter_->Delete(); +} + +LifetimeActor *RoutingPolicyMgr::deleter() { + return deleter_.get(); +} + +bool RoutingPolicyMgr::deleted() { + return deleter()->IsDeleted(); +} + +RoutingPolicy *RoutingPolicyMgr::CreateRoutingPolicy( + const BgpRoutingPolicyConfig *config) { + RoutingPolicy *policy = GetRoutingPolicy(config->name()); + + if (policy) { + if (policy->deleted()) { + return NULL; + } + return policy; + } + + policy = BgpObjectFactory::Create( + config->name(), server_, this, config); + routing_policies_.insert(std::make_pair(config->name(), policy)); + policy->ProcessConfig(); + + return policy; +} + +void RoutingPolicyMgr::UpdateRoutingPolicy( + const BgpRoutingPolicyConfig *config) { + CHECK_CONCURRENCY("bgp::Config"); + + RoutingPolicy *policy = GetRoutingPolicy(config->name()); + if (policy && policy->deleted()) { + return; + } else if (!policy) { + return; + } + + policy->UpdateConfig(config); +} + +// +// Concurrency: BGP Config task +// +// Trigger deletion of a particular routing-policy +// +void RoutingPolicyMgr::DeleteRoutingPolicy(const std::string &name) { + CHECK_CONCURRENCY("bgp::Config"); + + RoutingPolicy *policy = GetRoutingPolicy(name); + + if (policy && policy->deleted()) { + return; + } else if (!policy) { + return; + } + + policy->ClearConfig(); + + policy->ManagedDelete(); +} + +// +// Concurrency: Called from BGP config task manager +// +void RoutingPolicyMgr::DestroyRoutingPolicy(RoutingPolicy *policy) { + CHECK_CONCURRENCY("bgp::Config"); + + const std::string name = policy->name(); + routing_policies_.erase(name); + delete policy; + + if (deleted()) return; + + const BgpRoutingPolicyConfig *config + = server()->config_manager()->FindRoutingPolicy(name); + if (config) { + CreateRoutingPolicy(config); + return; + } +} + +RoutingPolicy::PolicyResult RoutingPolicyMgr::ApplyPolicy( + const RoutingPolicy *policy, const BgpRoute *route, + BgpAttr *attr) const { + return (*policy)(route, attr); +} + +class RoutingPolicy::DeleteActor : public LifetimeActor { +public: + DeleteActor(BgpServer *server, RoutingPolicy *parent) + : LifetimeActor(server->lifetime_manager()), parent_(parent) { + } + virtual bool MayDelete() const { + return parent_->MayDelete(); + } + virtual void Shutdown() { + parent_->Shutdown(); + } + virtual void Destroy() { + parent_->mgr_->DestroyRoutingPolicy(parent_); + } + +private: + RoutingPolicy *parent_; +}; + +RoutingPolicy::RoutingPolicy(std::string name, BgpServer *server, + RoutingPolicyMgr *mgr, + const BgpRoutingPolicyConfig *config) + : name_(name), server_(server), mgr_(mgr), config_(config), + deleter_(new DeleteActor(server, this)), + manager_delete_ref_(this, mgr->deleter()), refcount_(0), generation_(0) { +} + +RoutingPolicy::~RoutingPolicy() { + STLDeleteValues(&terms_); +} + +PolicyTerm *RoutingPolicy::BuildTerm(const RoutingPolicyTerm &cfg_term) { + PolicyTerm::ActionList actions; + PolicyTerm::MatchList matches; + // Build the Match object + if (!cfg_term.match.community_match.empty()) { + std::vector communities_to_match = + boost::assign::list_of(cfg_term.match.community_match); + MatchCommunity *community = + new MatchCommunity(communities_to_match); + matches.push_back(community); + } + if (!cfg_term.match.prefix_match.prefix_to_match.empty()) { + boost::system::error_code ec; + Ip4Address ip4; + int plen; + ec = Ip4PrefixParse(cfg_term.match.prefix_match.prefix_to_match, + &ip4, &plen); + if (ec.value() == 0) { + PrefixMatchInet *prefix = + new PrefixMatchInet(cfg_term.match.prefix_match.prefix_to_match, + cfg_term.match.prefix_match.prefix_match_type); + matches.push_back(prefix); + } else { + Ip6Address ip6; + ec = Inet6PrefixParse(cfg_term.match.prefix_match.prefix_to_match, + &ip6, &plen); + if (ec.value() == 0) { + PrefixMatchInet6 *prefix = new + PrefixMatchInet6(cfg_term.match.prefix_match.prefix_to_match, + cfg_term.match.prefix_match.prefix_match_type); + matches.push_back(prefix); + } + } + } + // Build the Action object + if (cfg_term.action.action == RoutingPolicyActionConfig::REJECT) { + RoutingPolicyRejectAction *action = new RoutingPolicyRejectAction(); + actions.push_back(action); + } else if (cfg_term.action.action == RoutingPolicyActionConfig::NEXT_TERM) { + RoutingPolicyNexTermAction *action = new RoutingPolicyNexTermAction(); + actions.push_back(action); + } else if (cfg_term.action.action == RoutingPolicyActionConfig::ACCEPT) { + RoutingPolicyAcceptAction *action = new RoutingPolicyAcceptAction(); + actions.push_back(action); + } + + if (!cfg_term.action.update.community_set.empty()) { + UpdateCommunity *set_comm = + new UpdateCommunity(cfg_term.action.update.community_set, "set"); + actions.push_back(set_comm); + } + + if (!cfg_term.action.update.community_remove.empty()) { + UpdateCommunity *remove_comm = + new UpdateCommunity(cfg_term.action.update.community_remove, "remove"); + actions.push_back(remove_comm); + } + + if (!cfg_term.action.update.community_add.empty()) { + UpdateCommunity *add_comm = + new UpdateCommunity(cfg_term.action.update.community_add, "add"); + actions.push_back(add_comm); + } + + if (cfg_term.action.update.local_pref) { + UpdateLocalPref *local_pref = + new UpdateLocalPref(cfg_term.action.update.local_pref); + actions.push_back(local_pref); + } + + PolicyTerm *ret_term = NULL; + if (!actions.empty() || !matches.empty()) { + ret_term = new PolicyTerm(); + ret_term->set_actions(actions); + ret_term->set_matches(matches); + } + + return ret_term; +} + +void RoutingPolicy::ProcessConfig() { + BOOST_FOREACH(const RoutingPolicyTerm cfg_term, config_->terms()) { + // Build each terms and insert to operational data + PolicyTerm *term = BuildTerm(cfg_term); + add_term(term); + } +} + +void RoutingPolicy::UpdateConfig(const BgpRoutingPolicyConfig *cfg) { + CHECK_CONCURRENCY("bgp::Config"); + config_ = cfg; +} + +void RoutingPolicy::ClearConfig() { + CHECK_CONCURRENCY("bgp::Config"); + config_ = NULL; +} + +void RoutingPolicy::ManagedDelete() { + deleter_->Delete(); +} + +void RoutingPolicy::Shutdown() { + CHECK_CONCURRENCY("bgp::Config"); + ClearConfig(); +} + +bool RoutingPolicy::MayDelete() const { + return (refcount_ == 0); +} + +LifetimeActor *RoutingPolicy::deleter() { + return deleter_.get(); +} + +const LifetimeActor *RoutingPolicy::deleter() const { + return deleter_.get(); +} + +bool RoutingPolicy::deleted() const { + return deleter()->IsDeleted(); +} + +// +// Attempt to enqueue a delete for the RoutingPolicy. +// +void RoutingPolicy::RetryDelete() { + if (!deleter_->IsDeleted()) + return; + deleter_->RetryDelete(); +} + +RoutingPolicy::PolicyResult RoutingPolicy::operator()(const BgpRoute *route, + BgpAttr *attr) const { + BOOST_FOREACH(PolicyTerm *term, terms()) { + bool terminal = term->terminal(); + bool matched = term->ApplyTerm(route, attr); + if (terminal && matched) { + return std::make_pair(terminal, + (*term->actions().begin())->accept()); + } + } + return std::make_pair(false, true); +} + +PolicyTerm::PolicyTerm() { +} + +PolicyTerm::~PolicyTerm() { + STLDeleteValues(&actions_); + STLDeleteValues(&matches_); +} + +bool PolicyTerm::terminal() const { + if (!actions().empty()) + return (*actions().begin())->terminal(); + return false; +} + +bool PolicyTerm::ApplyTerm(const BgpRoute *route, BgpAttr *attr) const { + bool matched = true; + BOOST_FOREACH(RoutingPolicyMatch *match, matches()) { + if (!(*match)(route, attr)) { + matched = false; + break; + } + } + if (matched) { + bool first = true; + BOOST_FOREACH(RoutingPolicyAction *action, actions()) { + // First action defines what to do with the route + // accept/reject/next-term + if (first) { + if (action->terminal()) { + if (!action->accept()) { + // out_attr is unaltered + break; + } + } + first = false; + } else { + RoutingPolicyUpdateAction *update = + static_cast(action); + (*update)(attr); + } + } + } + return matched; +} diff --git a/src/bgp/routing-policy/routing_policy.h b/src/bgp/routing-policy/routing_policy.h index 57d3932c148..549a30a0ed7 100644 --- a/src/bgp/routing-policy/routing_policy.h +++ b/src/bgp/routing-policy/routing_policy.h @@ -5,22 +5,180 @@ #ifndef SRC_BGP_ROUTING_POLICY_ROUTING_POLICY_H_ #define SRC_BGP_ROUTING_POLICY_ROUTING_POLICY_H_ +#include +#include + +#include +#include + +#include "base/lifetime.h" +#include "base/util.h" + #include class BgpServer; +class RoutingPolicyMgr; +class BgpRoutingPolicyConfig; +class RoutingPolicyMatch; +class RoutingPolicyAction; +class RoutingPolicyTerm; +class BgpAttr; +class BgpRoute; + +class PolicyTerm { +public: + typedef std::vector ActionList; + typedef std::vector MatchList; + PolicyTerm(); + ~PolicyTerm(); + bool terminal() const; + bool ApplyTerm(const BgpRoute *route, BgpAttr *attr) const; + void set_actions(const ActionList &actions) { + actions_ = actions; + } + void set_matches(const MatchList &matches) { + matches_ = matches; + } + const MatchList &matches() const { + return matches_; + } + const ActionList &actions() const { + return actions_; + } +private: + MatchList matches_; + ActionList actions_; +}; + +class RoutingPolicy { +public: + typedef std::vector RoutingPolicyTermList; + typedef std::pair PolicyResult; + RoutingPolicy(std::string name, BgpServer *server, + RoutingPolicyMgr *mgr, + const BgpRoutingPolicyConfig *config); + virtual ~RoutingPolicy(); + void ProcessConfig(); + void UpdateConfig(const BgpRoutingPolicyConfig *config); + void ClearConfig(); + void Shutdown(); + + bool MayDelete() const; + void RetryDelete(); + void ManagedDelete(); + LifetimeActor *deleter(); + const LifetimeActor *deleter() const; + bool deleted() const; + + const std::string &name() const { return name_; } + const BgpRoutingPolicyConfig *config() const { return config_; } + const RoutingPolicyMgr *manager() const { return mgr_; } + + BgpServer *server() { return server_; } + const BgpServer *server() const { return server_; } + + RoutingPolicyTermList &terms() { return terms_; } + const RoutingPolicyTermList &terms() const { return terms_; } + void add_term(PolicyTerm *term) { + terms_.push_back(term); + } + + PolicyResult operator()(const BgpRoute *route, BgpAttr *attr) const; + +private: + friend class RoutingPolicyMgr; + class DeleteActor; + friend void intrusive_ptr_add_ref(RoutingPolicy *policy); + friend void intrusive_ptr_release(RoutingPolicy *policy); + + PolicyTerm *BuildTerm(const RoutingPolicyTerm &term); + std::string name_; + BgpServer *server_; + RoutingPolicyMgr *mgr_; + const BgpRoutingPolicyConfig *config_; + boost::scoped_ptr deleter_; + LifetimeRef manager_delete_ref_; + + // Updated when routing policy undergoes a change + uint32_t refcount_; + uint32_t generation_; + RoutingPolicyTermList terms_; +}; + +inline void intrusive_ptr_add_ref(RoutingPolicy *policy) { + policy->refcount_++; +} + +inline void intrusive_ptr_release(RoutingPolicy *policy) { + assert(policy->refcount_ != 0); + if (--policy->refcount_ == 0) { + if (policy->MayDelete()) + policy->RetryDelete(); + } +} class RoutingPolicyMgr { public: - RoutingPolicyMgr(BgpServer *server); + typedef std::map RoutingPolicyList; + typedef RoutingPolicyList::iterator name_iterator; + typedef RoutingPolicyList::const_iterator const_name_iterator; + + explicit RoutingPolicyMgr(BgpServer *server); virtual ~RoutingPolicyMgr(); SandeshTraceBufferPtr trace_buffer() const { return trace_buf_; } -private: + name_iterator name_begin() { return routing_policies_.begin(); } + name_iterator name_end() { return routing_policies_.end(); } + name_iterator name_lower_bound(const std::string &name) { + return routing_policies_.lower_bound(name); + } + const_name_iterator name_cbegin() { return routing_policies_.begin(); } + const_name_iterator name_cend() { return routing_policies_.end(); } + const_name_iterator name_clower_bound(const std::string &name) { + return routing_policies_.lower_bound(name); + } + + RoutingPolicy *GetRoutingPolicy(const std::string &name) { + name_iterator it; + if ((it = routing_policies_.find(name)) != routing_policies_.end()) { + return it->second; + } + return NULL; + } + const RoutingPolicy *GetRoutingPolicy(const std::string &name) const { + const_name_iterator it; + if ((it = routing_policies_.find(name)) != routing_policies_.end()) { + return it->second; + } + return NULL; + } + + virtual RoutingPolicy *CreateRoutingPolicy( + const BgpRoutingPolicyConfig *config); + void UpdateRoutingPolicy(const BgpRoutingPolicyConfig *config); + virtual void DeleteRoutingPolicy(const std::string &name); + + + bool deleted(); + void ManagedDelete(); + + void DestroyRoutingPolicy(RoutingPolicy *policy); + + size_t count() const { return routing_policies_.size(); } BgpServer *server() { return server_; } - const BgpServer *server() const { return server_; }; + const BgpServer *server() const { return server_; } + LifetimeActor *deleter(); + + RoutingPolicy::PolicyResult ApplyPolicy(const RoutingPolicy *policy, + const BgpRoute *route, BgpAttr *attr) const; + +private: + class DeleteActor; + BgpServer *server_; + RoutingPolicyList routing_policies_; + boost::scoped_ptr deleter_; + LifetimeRef server_delete_ref_; SandeshTraceBufferPtr trace_buf_; }; #endif // SRC_BGP_ROUTING_POLICY_ROUTING_POLICY_H_ - - diff --git a/src/bgp/routing-policy/routing_policy_action.cc b/src/bgp/routing-policy/routing_policy_action.cc new file mode 100644 index 00000000000..5b9f63b33a0 --- /dev/null +++ b/src/bgp/routing-policy/routing_policy_action.cc @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ + +#include "bgp/routing-policy/routing_policy_action.h" + +#include + +#include + +#include +#include +#include +#include + + +UpdateCommunity::UpdateCommunity(const std::vector communities, + std::string op) { + BOOST_FOREACH(const std::string &community, communities) { + uint32_t value = CommunityType::CommunityFromString(community); + if (value) communities_.push_back(value); + } + std::sort(communities_.begin(), communities_.end()); + std::vector::iterator it = + std::unique(communities_.begin(), communities_.end()); + communities_.erase(it, communities_.end()); + + if (strcmp(op.c_str(), "add") == 0) { + op_ = ADD; + } else if (strcmp(op.c_str(), "remove") == 0) { + op_ = REMOVE; + } else if (strcmp(op.c_str(), "set") == 0) { + op_ = SET; + } +} + +void UpdateCommunity::operator()(BgpAttr *attr) const { + if (!attr) return; + const Community *comm = attr->community(); + if (comm) { + BgpAttrDB *attr_db = attr->attr_db(); + BgpServer *server = attr_db->server(); + CommunityDB *comm_db = server->comm_db(); + CommunityPtr new_community; + if (op_ == SET) { + new_community = comm_db->SetAndLocate(comm, communities_); + } else if (op_ == ADD) { + new_community = comm_db->AppendAndLocate(comm, communities_); + } else if (op_ == REMOVE) { + new_community = comm_db->RemoveAndLocate(comm, communities_); + } + attr->set_community(new_community); + } +} + +std::string UpdateCommunity::ToString() const { + return "Update Community"; +} + +UpdateLocalPref::UpdateLocalPref(uint32_t local_pref) + : local_pref_(local_pref) { +} + +void UpdateLocalPref::operator()(BgpAttr *attr) const { + attr->set_local_pref(local_pref_); +} + +std::string UpdateLocalPref::ToString() const { + return "Update Community"; +} diff --git a/src/bgp/routing-policy/routing_policy_action.h b/src/bgp/routing-policy/routing_policy_action.h new file mode 100644 index 00000000000..101e58a9223 --- /dev/null +++ b/src/bgp/routing-policy/routing_policy_action.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_BGP_ROUTING_POLICY_ROUTING_POLICY_ACTION_H_ +#define SRC_BGP_ROUTING_POLICY_ROUTING_POLICY_ACTION_H_ + +#include +#include +#include + +class BgpAttr; + +class RoutingPolicyAction { +public: + virtual ~RoutingPolicyAction() {} + // Whether the action is terminal (Accept/Reject) + virtual bool terminal() const = 0; + virtual bool accept() const = 0; + virtual std::string ToString() const = 0; +}; + +class RoutingPolicyUpdateAction : public RoutingPolicyAction { +public: + virtual ~RoutingPolicyUpdateAction() {} + bool terminal() const { return false; } + bool accept() const { return true; } + virtual void operator()(BgpAttr *out_attr) const = 0; +}; + +class RoutingPolicyAcceptAction : public RoutingPolicyAction { +public: + virtual ~RoutingPolicyAcceptAction() {} + bool terminal() const { return true; } + bool accept() const { return true; } + std::string ToString() const { + return "accept"; + } +}; + +class RoutingPolicyRejectAction : public RoutingPolicyAction { +public: + virtual ~RoutingPolicyRejectAction() {} + bool terminal() const { return true; } + bool accept() const { return false; } + std::string ToString() const { + return "reject"; + } +}; + +class RoutingPolicyNexTermAction : public RoutingPolicyAction { +public: + virtual ~RoutingPolicyNexTermAction() {} + bool terminal() const { return false; } + bool accept() const { return false; } + std::string ToString() const { + return "next-term"; + } +}; + +class UpdateCommunity : public RoutingPolicyUpdateAction { +public: + typedef std::vector CommunityList; + enum CommunityUpdateOp { + ADD, + REMOVE, + SET + }; + UpdateCommunity(const std::vector communities, std::string op); + virtual ~UpdateCommunity() {}; + virtual void operator()(BgpAttr *out_attr) const; + std::string ToString() const; +private: + CommunityList communities_; + CommunityUpdateOp op_; +}; + +class UpdateLocalPref : public RoutingPolicyUpdateAction { +public: + UpdateLocalPref(uint32_t local_pref); + virtual ~UpdateLocalPref() {} + virtual void operator()(BgpAttr *out_attr) const; + std::string ToString() const; +private: + uint32_t local_pref_; +}; +#endif // SRC_BGP_ROUTING_POLICY_ROUTING_POLICY_ACTION_H_ diff --git a/src/bgp/routing-policy/routing_policy_match.cc b/src/bgp/routing-policy/routing_policy_match.cc new file mode 100644 index 00000000000..351f649a63a --- /dev/null +++ b/src/bgp/routing-policy/routing_policy_match.cc @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ + +#include "bgp/routing-policy/routing_policy_match.h" + +#include + +#include + +#include +#include + +MatchCommunity::MatchCommunity(const std::vector &communities) { + BOOST_FOREACH(const std::string &community, communities) { + uint32_t value = CommunityType::CommunityFromString(community); + // Invalid community from config is ignored + if (value) { + to_match_.push_back(value); + } + } + + std::sort(to_match_.begin(), to_match_.end()); + std::vector::iterator it = + std::unique(to_match_.begin(), to_match_.end()); + to_match_.erase(it, to_match_.end()); +} + +MatchCommunity::~MatchCommunity() { +} + +bool MatchCommunity::Match(const BgpRoute *route, + const BgpAttr *attr) const { + const Community *comm = attr->community(); + if (comm) { + std::vector list = comm->communities(); + if (list.size() < to_match_.size()) return false; + std::sort(list.begin(), list.end()); + if (std::includes(list.begin(), list.end(), + to_match_.begin(), to_match_.end())) return true; + } + + return false; +} + +std::string MatchCommunity::ToString() const { + return "Match community"; +} + +template +MatchPrefix::MatchPrefix(const std::string &prefix, + const std::string &match_type) { + boost::system::error_code ec; + match_prefix_ = PrefixT::FromString(prefix, &ec); + if (strcmp(match_type.c_str(), "exact") == 0) { + match_type_ = EXACT; + } else if (strcmp(match_type.c_str(), "longer") == 0) { + match_type_ = LONGER; + } else if (strcmp(match_type.c_str(), "orlonger") == 0) { + match_type_ = ORLONGER; + } +} + +template +MatchPrefix::~MatchPrefix() { +} + +template +bool MatchPrefix::Match(const BgpRoute *route, + const BgpAttr *attr) const { + const RouteT *in_route = dynamic_cast(route); + if (in_route == NULL) return false; + const PrefixT &prefix = in_route->GetPrefix(); + if (match_type_ == EXACT) { + if (prefix == match_prefix_) return true; + } else if (match_type_ == LONGER) { + if (prefix == match_prefix_) return false; + if (prefix.IsMoreSpecific(match_prefix_)) return true; + } else if (match_type_ == ORLONGER) { + if (prefix.IsMoreSpecific(match_prefix_)) return true; + } + return false; +} + +template +std::string MatchPrefix::ToString() const { + return "Match Prefix"; +} + +template class MatchPrefix; +template class MatchPrefix; diff --git a/src/bgp/routing-policy/routing_policy_match.h b/src/bgp/routing-policy/routing_policy_match.h new file mode 100644 index 00000000000..01263e3fc8d --- /dev/null +++ b/src/bgp/routing-policy/routing_policy_match.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_BGP_ROUTING_POLICY_ROUTING_POLICY_MATCH_H_ +#define SRC_BGP_ROUTING_POLICY_ROUTING_POLICY_MATCH_H_ + +#include +#include + +#include + +#include "bgp/inet/inet_route.h" +#include "bgp/inet6/inet6_route.h" + +class BgpAttr; +class BgpRoute; +class Community; + +class RoutingPolicyMatch { +public: + virtual std::string ToString() const = 0; + virtual ~RoutingPolicyMatch() { + } + bool operator()(const BgpRoute *route, const BgpAttr *attr) const { + return Match(route, attr); + } + virtual bool Match(const BgpRoute *route, const BgpAttr *attr) const = 0; +}; + +class MatchCommunity: public RoutingPolicyMatch { +public: + typedef std::vector CommunityList; + explicit MatchCommunity(const std::vector &communities); + virtual ~MatchCommunity(); + virtual bool Match(const BgpRoute *route, const BgpAttr *attr) const; + virtual std::string ToString() const; +private: + CommunityList to_match_; +}; + +template +struct PrefixMatchBase { + typedef T1 RouteT; + typedef T2 PrefixT; +}; + +class InetPrefixMatch : public PrefixMatchBase { +}; + +class Inet6PrefixMatch : public PrefixMatchBase { +}; + +template +class MatchPrefix : public RoutingPolicyMatch { +public: + typedef typename T::RouteT RouteT; + typedef typename T::PrefixT PrefixT; + enum MatchType { + EXACT, + LONGER, + ORLONGER, + }; + explicit MatchPrefix(const std::string &prefix, + const std::string &match_type="exact"); + virtual ~MatchPrefix(); + virtual bool Match(const BgpRoute *route, const BgpAttr *attr) const; + virtual std::string ToString() const; +private: + PrefixT match_prefix_; + MatchType match_type_; +}; + +typedef MatchPrefix PrefixMatchInet; +typedef MatchPrefix PrefixMatchInet6; +#endif // SRC_BGP_ROUTING_POLICY_ROUTING_POLICY_MATCH_H_ diff --git a/src/bgp/test/SConscript b/src/bgp/test/SConscript index f35b130d36d..2657e873a84 100644 --- a/src/bgp/test/SConscript +++ b/src/bgp/test/SConscript @@ -345,6 +345,10 @@ routing_instance_test = env.UnitTest('routing_instance_test', ['routing_instance_test.cc']) env.Alias('src/bgp:routing_instance_test', routing_instance_test) +routing_policy_test = env.UnitTest('routing_policy_test', + ['routing_policy_test.cc']) +env.Alias('src/bgp:routing_policy_test', routing_policy_test) + rt_network_attr_test = env.UnitTest('rt_network_attr_test', ['rt_network_attr_test.cc']) env.Alias('src/bgp:rt_network_attr_test', rt_network_attr_test) diff --git a/src/bgp/test/bgp_config_listener_test.cc b/src/bgp/test/bgp_config_listener_test.cc index 1517fbc708d..14515b44cfc 100644 --- a/src/bgp/test/bgp_config_listener_test.cc +++ b/src/bgp/test/bgp_config_listener_test.cc @@ -1777,6 +1777,8 @@ TEST_F(BgpConfigListenerTest, RoutingPolicyUpdate_3) { // // Trigger edge change between routing policy and routing instance +// In this test, modify link between mid-node(routing-instance-routing-policy) +// routing-policy // Validate both routing instance and routing policy are added to change list // TEST_F(BgpConfigListenerTest, RoutingPolicyUpdate_4) { @@ -1811,6 +1813,8 @@ TEST_F(BgpConfigListenerTest, RoutingPolicyUpdate_4) { // // Trigger edge change between routing policy and routing instance +// In this test, modify link between mid-node(routing-instance-routing-policy) +// routing-instance // Validate both routing instance and routing policy are added to change list // TEST_F(BgpConfigListenerTest, RoutingPolicyUpdate_5) { @@ -1913,7 +1917,6 @@ TEST_F(BgpConfigListenerTest, RoutingPolicyUpdate_7) { task_util::WaitForIdle(); } -// // // If multiple routing policies are linked to a routing instance, // a change of routing-instance will not put routing policies @@ -1949,6 +1952,65 @@ TEST_F(BgpConfigListenerTest, RoutingPolicyUpdate_8) { task_util::WaitForIdle(); } +// +// RI1 --> RP1 <-- RI2 +// | | +// -----> RP2 <---- +// Routing instance refers to two routing policies and each routing policy is +// referred by two routing instances +// Now update the one routing policy and verify that both routing instances are +// in change list +// +TEST_F(BgpConfigListenerTest, RoutingPolicyUpdate_9) { + string content = ReadFile("controller/src/bgp/testdata/config_listener_test_14.xml"); + EXPECT_TRUE(parser_.Parse(content)); + TASK_UTIL_EXPECT_EQ(0, GetChangeListCount()); + + PauseChangeListPropagation(); + // Trigger change on routing-policy which is linked to two routing instances + string id_name = "basic_0"; + ifmap_test_util::IFMapNodeNotify(&db_, "routing-policy", id_name); + task_util::WaitForIdle(); + + TASK_UTIL_EXPECT_EQ(1, GetChangeListCount()); + TASK_UTIL_EXPECT_EQ(1, GetNodeListCount()); + TASK_UTIL_EXPECT_EQ(0, GetEdgeListCount()); + + PerformChangeListPropagation(); + TASK_UTIL_EXPECT_EQ(4, GetChangeListCount()); + TASK_UTIL_EXPECT_EQ(2, GetChangeListCount("routing-policy")); + TASK_UTIL_EXPECT_EQ(2, GetChangeListCount("routing-instance")); + TASK_UTIL_EXPECT_EQ(0, GetChangeListCount("routing-instance-routing-policy")); + + ResumeChangeListPropagation(); + TASK_UTIL_EXPECT_EQ(0, GetChangeListCount()); + + PauseChangeListPropagation(); + // Trigger change on other routing-policy which is linked to + // two routing instances + id_name = "basic_1"; + ifmap_test_util::IFMapNodeNotify(&db_, "routing-policy", id_name); + task_util::WaitForIdle(); + + TASK_UTIL_EXPECT_EQ(1, GetChangeListCount()); + TASK_UTIL_EXPECT_EQ(1, GetNodeListCount()); + TASK_UTIL_EXPECT_EQ(0, GetEdgeListCount()); + + PerformChangeListPropagation(); + TASK_UTIL_EXPECT_EQ(4, GetChangeListCount()); + TASK_UTIL_EXPECT_EQ(2, GetChangeListCount("routing-policy")); + TASK_UTIL_EXPECT_EQ(2, GetChangeListCount("routing-instance")); + TASK_UTIL_EXPECT_EQ(0, GetChangeListCount("routing-instance-routing-policy")); + + ResumeChangeListPropagation(); + TASK_UTIL_EXPECT_EQ(0, GetChangeListCount()); + + boost::replace_all(content, "", ""); + boost::replace_all(content, "", ""); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); +} + int main(int argc, char **argv) { bgp_log_test::init(); ControlNode::SetDefaultSchedulingPolicy(); diff --git a/src/bgp/test/bgp_config_test.cc b/src/bgp/test/bgp_config_test.cc index 4561f161ae4..b320abf6849 100644 --- a/src/bgp/test/bgp_config_test.cc +++ b/src/bgp/test/bgp_config_test.cc @@ -4,6 +4,10 @@ #include +#include + +#include +#include #include "base/test/task_test_util.h" #include "bgp/bgp_config_ifmap.h" @@ -12,6 +16,7 @@ #include "bgp/bgp_log.h" #include "bgp/inet/inet_table.h" #include "bgp/routing-instance/peer_manager.h" +#include "bgp/routing-policy/routing_policy.h" #include "control-node/control_node.h" #include "db/db_graph.h" #include "db/test/db_test_util.h" @@ -1477,10 +1482,22 @@ TEST_F(BgpConfigTest, AddressFamilies3) { } TEST_F(BgpConfigTest, RoutePolicy_0) { - string content = FileRead("controller/src/bgp/testdata/routing_policy_0.xml"); + string content = + FileRead("controller/src/bgp/testdata/routing_policy_0.xml"); EXPECT_TRUE(parser_.Parse(content)); task_util::WaitForIdle(); + RoutingPolicy *policy = + server_.routing_policy_mgr()->GetRoutingPolicy("basic"); + TASK_UTIL_ASSERT_TRUE(policy != NULL); + TASK_UTIL_ASSERT_EQ(policy->terms().size(), 2); + + RoutingInstance *rti = + server_.routing_instance_mgr()->GetRoutingInstance("test"); + TASK_UTIL_ASSERT_TRUE(rti != NULL); + + RoutingInstance::RoutingPolicyList policies = rti->routing_policies(); + TASK_UTIL_ASSERT_TRUE(policies.size() == 1); boost::replace_all(content, "", ""); boost::replace_all(content, "", ""); EXPECT_TRUE(parser_.Parse(content)); @@ -1490,10 +1507,31 @@ TEST_F(BgpConfigTest, RoutePolicy_0) { } TEST_F(BgpConfigTest, RoutePolicy_1) { - string content = FileRead("controller/src/bgp/testdata/routing_policy_1.xml"); + string content = + FileRead("controller/src/bgp/testdata/routing_policy_1.xml"); EXPECT_TRUE(parser_.Parse(content)); task_util::WaitForIdle(); + RoutingPolicy *policy = + server_.routing_policy_mgr()->GetRoutingPolicy("basic_0"); + TASK_UTIL_ASSERT_TRUE(policy != NULL); + + policy = server_.routing_policy_mgr()->GetRoutingPolicy("basic_1"); + TASK_UTIL_ASSERT_TRUE(policy != NULL); + TASK_UTIL_ASSERT_EQ(policy->terms().size(), 1); + + RoutingInstance *rti = + server_.routing_instance_mgr()->GetRoutingInstance("test"); + TASK_UTIL_ASSERT_TRUE(rti != NULL); + + vector expect_list = boost::assign::list_of("basic_1")("basic_0"); + vector current_list; + RoutingInstance::RoutingPolicyList policies = rti->routing_policies(); + BOOST_FOREACH(RoutingPolicyPtr ptr, policies) { + current_list.push_back(ptr->name()); + } + TASK_UTIL_ASSERT_TRUE(policies.size() == 2); + TASK_UTIL_ASSERT_TRUE(current_list == expect_list); boost::replace_all(content, "", ""); boost::replace_all(content, "", ""); EXPECT_TRUE(parser_.Parse(content)); @@ -1503,10 +1541,84 @@ TEST_F(BgpConfigTest, RoutePolicy_1) { } TEST_F(BgpConfigTest, RoutePolicy_2) { - string content = FileRead("controller/src/bgp/testdata/routing_policy_2.xml"); + string content = + FileRead("controller/src/bgp/testdata/routing_policy_2.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + RoutingPolicy *policy = + server_.routing_policy_mgr()->GetRoutingPolicy("basic"); + TASK_UTIL_ASSERT_TRUE(policy != NULL); + TASK_UTIL_ASSERT_EQ(policy->terms().size(), 3); + + RoutingInstance *rti = + server_.routing_instance_mgr()->GetRoutingInstance("test"); + TASK_UTIL_ASSERT_TRUE(rti != NULL); + + RoutingInstance::RoutingPolicyList policies = rti->routing_policies(); + TASK_UTIL_ASSERT_TRUE(policies.size() == 1); + + 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_3) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_1a.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + RoutingPolicy *policy = + server_.routing_policy_mgr()->GetRoutingPolicy("basic_0"); + TASK_UTIL_ASSERT_TRUE(policy != NULL); + + policy = server_.routing_policy_mgr()->GetRoutingPolicy("basic_1"); + TASK_UTIL_ASSERT_TRUE(policy != NULL); + TASK_UTIL_ASSERT_EQ(policy->terms().size(), 1); + + RoutingInstance *rti = + server_.routing_instance_mgr()->GetRoutingInstance("test"); + TASK_UTIL_ASSERT_TRUE(rti != NULL); + + vector expect_list = boost::assign::list_of("basic_0")("basic_1"); + vector current_list; + RoutingInstance::RoutingPolicyList policies = rti->routing_policies(); + BOOST_FOREACH(RoutingPolicyPtr ptr, policies) { + current_list.push_back(ptr->name()); + } + TASK_UTIL_ASSERT_TRUE(policies.size() == 2); + TASK_UTIL_ASSERT_TRUE(current_list == expect_list); + 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_4) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_2a.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + RoutingPolicy *policy = + server_.routing_policy_mgr()->GetRoutingPolicy("basic"); + TASK_UTIL_ASSERT_TRUE(policy != NULL); + TASK_UTIL_ASSERT_EQ(policy->terms().size(), 4); + + RoutingInstance *rti = + server_.routing_instance_mgr()->GetRoutingInstance("test"); + TASK_UTIL_ASSERT_TRUE(rti != NULL); + + RoutingInstance::RoutingPolicyList policies = rti->routing_policies(); + TASK_UTIL_ASSERT_TRUE(policies.size() == 1); + boost::replace_all(content, "", ""); boost::replace_all(content, "", ""); EXPECT_TRUE(parser_.Parse(content)); @@ -1514,6 +1626,7 @@ TEST_F(BgpConfigTest, RoutePolicy_2) { 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/test/bgp_ifmap_config_manager_test.cc b/src/bgp/test/bgp_ifmap_config_manager_test.cc index c9276720384..20d42067bd4 100644 --- a/src/bgp/test/bgp_ifmap_config_manager_test.cc +++ b/src/bgp/test/bgp_ifmap_config_manager_test.cc @@ -10,6 +10,7 @@ #include #include "base/test/task_test_util.h" +#include "base/string_util.h" #include "bgp/bgp_config_parser.h" #include "bgp/bgp_factory.h" #include "bgp/bgp_ifmap_sandesh.h" @@ -26,7 +27,7 @@ #include "schema/bgp_schema_types.h" #include "schema/vnc_cfg_types.h" -using boost::assign::map_list_of; +using boost::assign::list_of; using namespace std; static string FileRead(const string &filename) { @@ -1945,7 +1946,7 @@ TEST_F(BgpIfmapConfigManagerTest, RoutingInstanceRoutingPolicy_0) { ASSERT_TRUE(test_ri != NULL); ASSERT_TRUE(test_ri->routing_policy_list().size() == 1); ASSERT_TRUE(test_ri->routing_policy_list().front().routing_policy_ == "basic_0"); - ASSERT_TRUE(test_ri->routing_policy_list().front().sequence_ == "1.0"); + ASSERT_TRUE(test_ri->routing_policy_list().front().sequence_ == 1.0); // Update the routing instance with two route policy string content_b = FileRead("controller/src/bgp/testdata/routing_policy_3d.xml"); @@ -1961,11 +1962,10 @@ TEST_F(BgpIfmapConfigManagerTest, RoutingInstanceRoutingPolicy_0) { ASSERT_TRUE(test_ri->routing_policy_list().size() == 2); BgpInstanceConfig::RoutingPolicyList list = test_ri->routing_policy_list(); - map expect_list = map_list_of("basic_0", "1.0")("basic_1", "2.0"); - map current_list; + vector expect_list = list_of("basic_0")("basic_1"); + vector current_list; BOOST_FOREACH(RoutingPolicyAttachInfo info, list) { - current_list.insert(pair(info.routing_policy_, - info.sequence_)); + current_list.push_back(info.routing_policy_); } ASSERT_TRUE(current_list.size() == expect_list.size()); @@ -2009,11 +2009,10 @@ TEST_F(BgpIfmapConfigManagerTest, RoutingInstanceRoutingPolicy_1) { ASSERT_TRUE(test_ri->routing_policy_list().size() == 2); BgpInstanceConfig::RoutingPolicyList list = test_ri->routing_policy_list(); - map expect_list = map_list_of("basic_0", "1.0")("basic_1", "2.0"); - map current_list; + vector expect_list = list_of("basic_0")("basic_1"); + vector current_list; BOOST_FOREACH(RoutingPolicyAttachInfo info, list) { - current_list.insert(pair(info.routing_policy_, - info.sequence_)); + current_list.push_back(info.routing_policy_); } ASSERT_TRUE(current_list.size() == expect_list.size()); @@ -2030,11 +2029,10 @@ TEST_F(BgpIfmapConfigManagerTest, RoutingInstanceRoutingPolicy_1) { ASSERT_TRUE(test_ri->routing_policy_list().size() == 2); list = test_ri->routing_policy_list(); - expect_list = map_list_of("basic_0", "2.0")("basic_1", "1.0"); + expect_list = list_of("basic_1")("basic_0"); current_list.clear(); BOOST_FOREACH(RoutingPolicyAttachInfo info, list) { - current_list.insert(pair(info.routing_policy_, - info.sequence_)); + current_list.push_back(info.routing_policy_); } ASSERT_TRUE(current_list.size() == expect_list.size()); @@ -2073,7 +2071,7 @@ TEST_F(BgpIfmapConfigManagerTest, RoutingInstanceRoutingPolicy_2) { ASSERT_TRUE(test_ri != NULL); ASSERT_TRUE(test_ri->routing_policy_list().size() == 1); ASSERT_TRUE(test_ri->routing_policy_list().front().routing_policy_ == "basic_0"); - ASSERT_TRUE(test_ri->routing_policy_list().front().sequence_ == "1.0"); + ASSERT_TRUE(test_ri->routing_policy_list().front().sequence_ == 1.0); // Remove the link between the routing-instance and the routing-policy. ifmap_test_util::IFMapMsgUnlink(&db_, @@ -2115,7 +2113,7 @@ TEST_F(BgpIfmapConfigManagerTest, RoutingInstanceRoutingPolicy_3) { ASSERT_TRUE(test_ri != NULL); ASSERT_TRUE(test_ri->routing_policy_list().size() == 1); ASSERT_TRUE(test_ri->routing_policy_list().front().routing_policy_ == "basic_0"); - ASSERT_TRUE(test_ri->routing_policy_list().front().sequence_ == "1.0"); + ASSERT_TRUE(test_ri->routing_policy_list().front().sequence_ == 1.0); string content_b = FileRead("controller/src/bgp/testdata/routing_policy_3c.xml"); EXPECT_TRUE(parser_.Parse(content_b)); diff --git a/src/bgp/test/routing_policy_test.cc b/src/bgp/test/routing_policy_test.cc new file mode 100644 index 00000000000..5c9eb3f052a --- /dev/null +++ b/src/bgp/test/routing_policy_test.cc @@ -0,0 +1,1165 @@ +/* + * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved. + */ + +#include "bgp/routing-policy/routing_policy.h" + +#include + +#include +#include + +#include "bgp/bgp_config_ifmap.h" +#include "bgp/bgp_config_parser.h" +#include "bgp/bgp_factory.h" +#include "bgp/inet/inet_table.h" +#include "bgp/inet6/inet6_table.h" +#include "bgp/l3vpn/inetvpn_table.h" +#include "bgp/origin-vn/origin_vn.h" +#include "bgp/routing-instance/rtarget_group_mgr.h" +#include "bgp/test/bgp_server_test_util.h" +#include "bgp/test/bgp_test_util.h" +#include "control-node/control_node.h" +#include "db/test/db_test_util.h" +#include "ifmap/ifmap_link_table.h" +#include "ifmap/ifmap_server_parser.h" +#include "ifmap/test/ifmap_test_util.h" +#include "net/community_type.h" +#include "schema/bgp_schema_types.h" +#include "schema/vnc_cfg_types.h" + +using namespace std; +using boost::assign::list_of; +using boost::assign::map_list_of; + +static string FileRead(const string &filename) { + ifstream file(filename.c_str()); + string content((istreambuf_iterator(file)), + istreambuf_iterator()); + return content; +} + +template +struct TypeDefinition { + typedef T1 TableT; + typedef T2 PrefixT; +}; + +// TypeDefinitions that we want to test. +typedef TypeDefinition InetDefinition; +typedef TypeDefinition Inet6Definition; + +class BgpPeerMock : public IPeer { +public: + BgpPeerMock(const Ip4Address &address) : address_(address) { } + virtual ~BgpPeerMock() { } + virtual std::string ToString() const { + return address_.to_string(); + } + virtual std::string ToUVEKey() const { + return address_.to_string(); + } + virtual bool SendUpdate(const uint8_t *msg, size_t msgsize) { + return true; + } + virtual BgpServer *server() { + return NULL; + } + virtual IPeerClose *peer_close() { + return NULL; + } + virtual IPeerDebugStats *peer_stats() { + return NULL; + } + virtual const IPeerDebugStats *peer_stats() const { + return NULL; + } + virtual bool IsReady() const { + return true; + } + virtual bool IsXmppPeer() const { return false; } + virtual void Close() { + } + BgpProto::BgpPeerType PeerType() const { + return BgpProto::IBGP; + } + virtual uint32_t bgp_identifier() const { + return htonl(address_.to_ulong()); + } + virtual const std::string GetStateName() const { + return ""; + } + virtual void UpdateRefCount(int count) const { } + virtual tbb::atomic GetRefCount() const { + tbb::atomic count; + count = 0; + return count; + } + virtual void UpdatePrimaryPathCount(int count) const { } + virtual int GetPrimaryPathCount() const { return 0; } + +private: + Ip4Address address_; +}; + +#define VERIFY_EQ(expected, actual) \ + TASK_UTIL_EXPECT_EQ(expected, actual) + +static const char *bgp_server_config = "\ +\ + \ + 192.168.0.100\ +
192.168.0.100
\ + 64496\ +
\ +
\ +"; + +class RoutingPolicyTest : public ::testing::Test { +protected: + RoutingPolicyTest() : bgp_server_(new BgpServer(&evm_)), + parser_(&config_db_) { + IFMapLinkTable_Init(&config_db_, &config_graph_); + vnc_cfg_Server_ModuleInit(&config_db_, &config_graph_); + bgp_schema_Server_ModuleInit(&config_db_, &config_graph_); + } + ~RoutingPolicyTest() { + STLDeleteValues(&peers_); + } + + virtual void SetUp() { + IFMapServerParser *parser = IFMapServerParser::GetInstance("schema"); + vnc_cfg_ParserInit(parser); + bgp_schema_ParserInit(parser); + BgpIfmapConfigManager *config_manager = + static_cast( + bgp_server_->config_manager()); + config_manager->Initialize(&config_db_, &config_graph_, "localhost"); + bgp_server_->rtarget_group_mgr()->Initialize(); + BgpConfigParser bgp_parser(&config_db_); + bgp_parser.Parse(bgp_server_config); + task_util::WaitForIdle(); + } + + virtual void TearDown() { + task_util::WaitForIdle(); + bgp_server_->Shutdown(); + task_util::WaitForIdle(); + db_util::Clear(&config_db_); + IFMapServerParser *parser = IFMapServerParser::GetInstance("schema"); + parser->MetadataClear("schema"); + } + + void NetworkConfig(const vector &instance_names, + const multimap &connections) { + string netconf( + bgp_util::NetworkConfigGenerate(instance_names, connections)); + IFMapServerParser *parser = + IFMapServerParser::GetInstance("schema"); + parser->Receive(&config_db_, netconf.data(), netconf.length(), 0); + } + + + void DeleteRoutingInstance(const string &instance_name, const string &rt_name) { + ifmap_test_util::IFMapMsgUnlink(&config_db_, "routing-instance", instance_name, + "virtual-network", instance_name, "virtual-network-routing-instance"); + ifmap_test_util::IFMapMsgUnlink(&config_db_, "routing-instance", instance_name, + "route-target", rt_name, "instance-target"); + ifmap_test_util::IFMapMsgNodeDelete( + &config_db_, "virtual-network", instance_name); + ifmap_test_util::IFMapMsgNodeDelete( + &config_db_, "routing-instance", instance_name); + ifmap_test_util::IFMapMsgNodeDelete( + &config_db_, "route-target", rt_name); + task_util::WaitForIdle(); + } + + void VerifyTableNoExists(const string &table_name) { + TASK_UTIL_EXPECT_TRUE( + bgp_server_->database()->FindTable(table_name) == NULL); + } + + template + void AddRoute(IPeer *peer, const string &table_name, + const string &prefix, int localpref, + const vector &community_list = vector()) { + typedef typename T::TableT TableT; + typedef typename T::PrefixT PrefixT; + boost::system::error_code error; + PrefixT nlri = PrefixT::FromString(prefix, &error); + EXPECT_FALSE(error); + DBRequest request; + request.oper = DBRequest::DB_ENTRY_ADD_CHANGE; + request.key.reset(new typename TableT::RequestKey(nlri, peer)); + BgpAttrSpec attr_spec; + boost::scoped_ptr local_pref( + new BgpAttrLocalPref(localpref)); + attr_spec.push_back(local_pref.get()); + CommunitySpec spec; + if (!community_list.empty()) { + BOOST_FOREACH(string comm, community_list) { + boost::system::error_code error; + uint32_t community = + CommunityType::CommunityFromString(comm, &error); + spec.communities.push_back(community); + } + attr_spec.push_back(&spec); + } + + BgpAttrPtr attr = bgp_server_->attr_db()->Locate(attr_spec); + request.data.reset(new BgpTable::RequestData(attr, 0, 0)); + BgpTable *table = static_cast + (bgp_server_->database()->FindTable(table_name)); + ASSERT_TRUE(table != NULL); + table->Enqueue(&request); + task_util::WaitForIdle(); + } + + template + void DeleteRoute(IPeer *peer, const string &table_name, + const string &prefix) { + typedef typename T::TableT TableT; + typedef typename T::PrefixT PrefixT; + boost::system::error_code error; + PrefixT nlri = PrefixT::FromString(prefix, &error); + EXPECT_FALSE(error); + + DBRequest request; + request.oper = DBRequest::DB_ENTRY_DELETE; + request.key.reset(new typename TableT::RequestKey(nlri, peer)); + + BgpTable *table = static_cast + (bgp_server_->database()->FindTable(table_name)); + ASSERT_TRUE(table != NULL); + + table->Enqueue(&request); + } + + int RouteCount(const string &table_name) const { + BgpTable *table = static_cast( + bgp_server_->database()->FindTable(table_name)); + EXPECT_TRUE(table != NULL); + if (table == NULL) { + return 0; + } + return table->Size(); + } + + template + BgpRoute *RouteLookup(const string &table_name, const string &prefix) { + typedef typename T::TableT TableT; + typedef typename T::PrefixT PrefixT; + BgpTable *table = dynamic_cast( + bgp_server_->database()->FindTable(table_name)); + EXPECT_TRUE(table != NULL); + if (table == NULL) { + return NULL; + } + boost::system::error_code error; + PrefixT nlri = PrefixT::FromString(prefix, &error); + EXPECT_FALSE(error); + typename TableT::RequestKey key(nlri, NULL); + BgpRoute *rt = static_cast(table->Find(&key)); + return rt; + } + + + vector GetOriginalCommunityListFromRoute(const BgpPath *path) { + const Community *comm = path->GetOriginalPathAttr()->community(); + if (comm == NULL) return vector(); + vector list; + BOOST_FOREACH(uint32_t community, comm->communities()) { + list.push_back(CommunityType::CommunityToString(community)); + } + sort(list.begin(), list.end()); + return list; + } + + + vector GetCommunityListFromRoute(const BgpPath *path) { + const Community *comm = path->GetAttr()->community(); + if (comm == NULL) return vector(); + vector list; + BOOST_FOREACH(uint32_t community, comm->communities()) { + list.push_back(CommunityType::CommunityToString(community)); + } + sort(list.begin(), list.end()); + return list; + } + + EventManager evm_; + DB config_db_; + DBGraph config_graph_; + boost::scoped_ptr bgp_server_; + vector peers_; + BgpConfigParser parser_; +}; + +TEST_F(RoutingPolicyTest, PolicyPrefixMatchUpdateLocalPref) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_0.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", + "10.0.1.1/32", 100); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "10.0.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + const BgpAttr *attr = rt->BestPath()->GetAttr(); + const BgpAttr *orig_attr = rt->BestPath()->GetOriginalPathAttr(); + uint32_t original_local_pref = orig_attr->local_pref(); + uint32_t policy_local_pref = attr->local_pref(); + ASSERT_TRUE(policy_local_pref == 102); + ASSERT_TRUE(original_local_pref == 100); + + DeleteRoute(peers_[0], "test.inet.0", "10.0.1.1/32"); +} + +TEST_F(RoutingPolicyTest, PolicyCommunityMatchReject) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_0.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "10.1.1.1/32", + 100, list_of("11:13")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "10.1.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + EXPECT_EQ(rt->BestPath()->GetFlags() & BgpPath::RoutingPolicyReject, + BgpPath::RoutingPolicyReject); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == false); + + DeleteRoute(peers_[0], "test.inet.0", "10.1.1.1/32"); +} + +TEST_F(RoutingPolicyTest, PolicyPrefixMatchAddCommunity) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_2.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.1.1.1/32", + 100, list_of("11:13")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.1.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.1.1/32"); +} + +TEST_F(RoutingPolicyTest, PolicyPrefixMatchRemoveCommunity) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_2b.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.1.1.1/32", 100, + list_of("11:13")("11:44")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.1.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), list_of("11:44")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.1.1/32"); +} + +TEST_F(RoutingPolicyTest, PolicyPrefixMatchSetCommunity) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_2c.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.1.1.1/32", 100, + list_of("23:13")("23:44")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.1.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), list_of("11:13")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("23:13")("23:44")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.1.1/32"); +} + +TEST_F(RoutingPolicyTest, PolicyPrefixMatchRemoveMultipleCommunity) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_2d.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.1.1.1/32", 100, + list_of("11:13")("11:22")("11:44")("22:44")("33:66")("44:88")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.1.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")("33:66")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:22")("11:44")("22:44")("33:66")("44:88")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.1.1/32"); +} + +TEST_F(RoutingPolicyTest, PolicyPrefixMatchRemoveMultipleCommunity_1) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_2d.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.1.1.1/32", 100, + list_of("11:13")("11:22")("11:44")("22:44")("33:66")("77:88")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.1.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")("33:66")("77:88")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:22")("11:44")("22:44")("33:66")("77:88")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.1.1/32"); +} + +TEST_F(RoutingPolicyTest, PolicyPrefixMatchAddMultipleCommunity) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_2e.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.1.1.1/32", 100, + list_of("11:13")("11:44")("33:66")("77:88")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.1.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:22")("11:44")("22:44")("33:66")("44:88")("77:88")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")("33:66")("77:88")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.1.1/32"); +} + +TEST_F(RoutingPolicyTest, PolicyPrefixMatchSetMultipleCommunity) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_2f.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.1.1.1/32", 100, + list_of("11:13")("11:44")("33:66")("77:88")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.1.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:22")("22:44")("44:88")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")("33:66")("77:88")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.1.1/32"); +} + +TEST_F(RoutingPolicyTest, PolicyPrefixMatch_MultipleCommunityAction) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_2g.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.1.1.1/32", 100, + list_of("22:44")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.1.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), list_of("11:22")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("22:44")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.1.1/32"); +} + +TEST_F(RoutingPolicyTest, PolicyPrefixMatch_SubnetMatch) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_2f.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.0.0.0/8", 100, + list_of("11:13")("11:44")("33:66")("77:88")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.0.0.0/8"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:22")("22:44")("44:88")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")("33:66")("77:88")); + DeleteRoute(peers_[0], "test.inet.0", "1.0.0.0/8"); +} + +TEST_F(RoutingPolicyTest, PolicyPrefixMatch_SubnetMatch_1) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_2f.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.1.0.0/16", 100, + list_of("11:13")("11:44")("33:66")("77:88")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.1.0.0/16"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:22")("22:44")("44:88")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")("33:66")("77:88")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.0.0/16"); +} + +TEST_F(RoutingPolicyTest, PolicyPrefixMatch_SubnetMatch_Longer) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_5.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.0.0.0/8", 100, + list_of("11:13")("11:44")("33:66")("77:88")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.0.0.0/8"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")("33:66")("77:88")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")("33:66")("77:88")); + DeleteRoute(peers_[0], "test.inet.0", "1.0.0.0/8"); +} + +TEST_F(RoutingPolicyTest, PolicyPrefixMatch_SubnetMatch_Longer_1) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_5.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.1.1.0/24", 100, + list_of("11:13")("11:44")("33:66")("77:88")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.1.1.0/24"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:22")("22:44")("44:88")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")("33:66")("77:88")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.1.0/24"); +} +// +// Test the match for exact prefix match +// Route is added with non matching prefix and ensure policy action is not taken +// +TEST_F(RoutingPolicyTest, PolicyPrefixMatch_Exact_NoMatch) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_5a.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "2.1.1.1/32", 100, + list_of("11:13")("11:44")("33:66")("77:88")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "2.1.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")("33:66")("77:88")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")("33:66")("77:88")); + DeleteRoute(peers_[0], "test.inet.0", "2.1.1.1/32"); +} + +// +// Test the match for exact prefix match +// Route is added with matching prefix and ensure policy action is not taken +// +TEST_F(RoutingPolicyTest, PolicyPrefixMatch_Exact_Match) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_5a.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.1.1.1/32", 100, + list_of("11:13")("11:44")("33:66")("77:88")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.1.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:22")("22:44")("44:88")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")("33:66")("77:88")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.1.1/32"); +} + +// +// Test the match for exact prefix match (non /32) +// Route is added with matching prefix and ensure policy action is not taken +// +TEST_F(RoutingPolicyTest, PolicyPrefixMatch_Exact_Match_1) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_5b.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.1.0.0/16", 100, + list_of("11:13")("11:44")("33:66")("77:88")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.1.0.0/16"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:22")("22:44")("44:88")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")("33:66")("77:88")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.0.0/16"); +} + +// +// Test multiple match policy term +// Route is added which matches multiple policy term +// Ensure that all policy action is taken +// +TEST_F(RoutingPolicyTest, PolicyMultipleMatch) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_6.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.1.1.1/32", + 100, list_of("11:13")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.1.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:22")("22:44")("44:88")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.1.1/32"); +} + +// +// Test multiple match policy term +// Route is added which matches the first policy term. Action of the first term +// add community that matches the second term. Action of second term adds +// community that is matched in third term +// Ensure that all policy action is taken +// +TEST_F(RoutingPolicyTest, PolicyMultipleMatch_1) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_6a.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.1.1.1/32", + 100, list_of("11:13")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.1.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:22")("22:44")("44:88")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.1.1/32"); +} + +// +// Test two policy term +// Route is added which matches the first policy term. Action of the first term +// add community that matches the second term. Action of second term drops the +// route +// Ensure that path is rejected +// +TEST_F(RoutingPolicyTest, PolicyMultipleMatch_2) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_6b.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet.0", "1.1.1.1/32", + 100, list_of("11:13")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = + RouteLookup("test.inet.0", "1.1.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == false); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:22")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.1.1/32"); +} + +// +// Policy match on ipv6 +// +TEST_F(RoutingPolicyTest, PolicyMatch_Inet6) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_7.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128", 100, list_of("11:13")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet6.0")); + BgpRoute *rt = RouteLookup("test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:22")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")); + DeleteRoute(peers_[0], "test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128"); +} + +// +// Policy match on ipv6 with v4 policies +// +TEST_F(RoutingPolicyTest, PolicyMatch_Inet6_V4PolicyMatch) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_7a.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128", 100, list_of("11:13")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet6.0")); + BgpRoute *rt = RouteLookup("test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), list_of("11:13")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")); + DeleteRoute(peers_[0], "test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128"); +} + +// +// Policy with both ipv6 & v4 matches +// Add inet and inet6 route and validate policy +// +TEST_F(RoutingPolicyTest, PolicyMatch_Inet6Inet4PolicyMatch) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_7b.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128", 100, list_of("11:13")); + task_util::WaitForIdle(); + AddRoute(peers_[0], "test.inet.0", + "1.1.1.1/32", 100, list_of("11:13")); + + VERIFY_EQ(1, RouteCount("test.inet6.0")); + VERIFY_EQ(1, RouteCount("test.inet.0")); + BgpRoute *rt = RouteLookup("test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:22")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")); + DeleteRoute(peers_[0], "test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128"); + + rt = RouteLookup("test.inet.0", "1.1.1.1/32"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:22")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")); + DeleteRoute(peers_[0], "test.inet.0", "1.1.1.1/32"); +} + +// +// Policy with two match conditions in a single term +// Add inet6 route which matches both condition and validate policy +// Policy action is applied +// +TEST_F(RoutingPolicyTest, PolicyMatch_Inet6_MultipleMatches) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_7c.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128", 100, list_of("11:13")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet6.0")); + BgpRoute *rt = RouteLookup("test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:22")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")); + DeleteRoute(peers_[0], "test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128"); +} + +// +// Policy with two match conditions in a single term +// Add inet6 route which matches only one condition and validate policy +// Policy action is not applied +// +TEST_F(RoutingPolicyTest, PolicyMatch_Inet6_MultipleMatches_1) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_7c.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + // Prefix Match .. community no match + AddRoute(peers_[0], "test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128", 100, list_of("99:13")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet6.0")); + BgpRoute *rt = RouteLookup("test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("99:13")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("99:13")); + DeleteRoute(peers_[0], "test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128"); +} + +// +// Policy with two match condition ipv6 in a single term +// Add inet6 route which matches no condition and validate policy +// Policy action is not applied +// +TEST_F(RoutingPolicyTest, PolicyMatch_Inet6_MultipleMatches_2) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_7c.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet6.0", + "2001:db7:85a3::8a2e:370:7334/128", 100, list_of("99:13")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet6.0")); + BgpRoute *rt = RouteLookup("test.inet6.0", + "2001:db7:85a3::8a2e:370:7334/128"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("99:13")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("99:13")); + DeleteRoute(peers_[0], "test.inet6.0", + "2001:db7:85a3::8a2e:370:7334/128"); +} + +// +// Policy with two match conditions and two actions in single term +// Add inet6 route which matches both condition and validate policy +// Policy action is applied +// +TEST_F(RoutingPolicyTest, PolicyMatch_Inet6_MultipleMatches_MultipleActions) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_7d.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128", 100, list_of("11:13")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet6.0")); + BgpRoute *rt = RouteLookup("test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:22")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")); + + const BgpAttr *attr = rt->BestPath()->GetAttr(); + const BgpAttr *orig_attr = rt->BestPath()->GetOriginalPathAttr(); + uint32_t original_local_pref = orig_attr->local_pref(); + uint32_t policy_local_pref = attr->local_pref(); + ASSERT_TRUE(policy_local_pref == 999); + ASSERT_TRUE(original_local_pref == 100); + DeleteRoute(peers_[0], "test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128"); +} + +TEST_F(RoutingPolicyTest, PolicyPrefixMatch_SubnetMatchV6) { + string content = + FileRead("controller/src/bgp/testdata/routing_policy_7e.xml"); + EXPECT_TRUE(parser_.Parse(content)); + task_util::WaitForIdle(); + + boost::system::error_code ec; + peers_.push_back( + new BgpPeerMock(Ip4Address::from_string("192.168.0.1", ec))); + + AddRoute(peers_[0], "test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128", 100, + list_of("11:13")("11:44")("33:66")("77:88")); + task_util::WaitForIdle(); + + VERIFY_EQ(1, RouteCount("test.inet6.0")); + BgpRoute *rt = RouteLookup("test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128"); + ASSERT_TRUE(rt != NULL); + VERIFY_EQ(peers_[0], rt->BestPath()->GetPeer()); + ASSERT_TRUE(rt->BestPath()->IsFeasible() == true); + ASSERT_EQ(GetCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")("77:88")); + ASSERT_EQ(GetOriginalCommunityListFromRoute(rt->BestPath()), + list_of("11:13")("11:44")("33:66")("77:88")); + DeleteRoute(peers_[0], "test.inet6.0", + "2001:db8:85a3::8a2e:370:7334/128"); +} + +class TestEnvironment : public ::testing::Environment { + virtual ~TestEnvironment() { } +}; + +static void SetUp() { + ControlNode::SetDefaultSchedulingPolicy(); + BgpObjectFactory::Register( + boost::factory()); +} + +static void TearDown() { + task_util::WaitForIdle(); + TaskScheduler *scheduler = TaskScheduler::GetInstance(); + scheduler->Terminate(); +} + +int main(int argc, char **argv) { + bgp_log_test::init(); + ::testing::InitGoogleTest(&argc, argv); + ::testing::AddGlobalTestEnvironment(new TestEnvironment()); + SetUp(); + int result = RUN_ALL_TESTS(); + TearDown(); + return result; +} diff --git a/src/bgp/testdata/config_listener_test_14.xml b/src/bgp/testdata/config_listener_test_14.xml new file mode 100644 index 00000000000..ef40388e24f --- /dev/null +++ b/src/bgp/testdata/config_listener_test_14.xml @@ -0,0 +1,41 @@ + + + + + + 23:13 + + + accept + + + + + + + 11:13 + + + accept + + + + + + 1.0 + + + 2.0 + + target:1:103 + + + + 1.0 + + + 2.0 + + target:1:103 + + diff --git a/src/bgp/testdata/config_listener_test_9.xml b/src/bgp/testdata/config_listener_test_9.xml index 487ead35580..fa10c924190 100644 --- a/src/bgp/testdata/config_listener_test_9.xml +++ b/src/bgp/testdata/config_listener_test_9.xml @@ -4,6 +4,10 @@ 23:13 + + 1/8 + orlonger + @@ -17,6 +21,10 @@ 23:11 + + 2001:db8:85a3:aaaa::b:c:d/64 + longer + reject diff --git a/src/bgp/testdata/routing_policy_0.xml b/src/bgp/testdata/routing_policy_0.xml index b69dca4b669..e2b6911a57d 100644 --- a/src/bgp/testdata/routing_policy_0.xml +++ b/src/bgp/testdata/routing_policy_0.xml @@ -3,7 +3,10 @@ - 23:13 + + 10.0.1.1/32 + exact + diff --git a/src/bgp/testdata/routing_policy_1.xml b/src/bgp/testdata/routing_policy_1.xml index 487ead35580..c2cd44a15e2 100644 --- a/src/bgp/testdata/routing_policy_1.xml +++ b/src/bgp/testdata/routing_policy_1.xml @@ -26,10 +26,10 @@ - 1.0 + 1.1 - 1.1 + 1.01 target:1:103 diff --git a/src/bgp/testdata/routing_policy_1a.xml b/src/bgp/testdata/routing_policy_1a.xml new file mode 100644 index 00000000000..0e35bf0f84d --- /dev/null +++ b/src/bgp/testdata/routing_policy_1a.xml @@ -0,0 +1,36 @@ + + + + + + 23:13 + + + + 102 + + accept + + + + + + + 23:11 + + + reject + + + + + + + 1.001 + + + 1.0011 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_2.xml b/src/bgp/testdata/routing_policy_2.xml index 04cccda11e9..1d448b10bbb 100644 --- a/src/bgp/testdata/routing_policy_2.xml +++ b/src/bgp/testdata/routing_policy_2.xml @@ -4,8 +4,8 @@ - 3.1.0.0/16 - longer + 3.1.0.0/16 + longer @@ -18,8 +18,8 @@ - 3.1.1.1 - exact + 3.1.1.1/32 + exact @@ -29,18 +29,17 @@ - 1/8 - orlonger + 1/8 + orlonger - - - - 11:44 - - - + + + 11:44 + + + accept diff --git a/src/bgp/testdata/routing_policy_2a.xml b/src/bgp/testdata/routing_policy_2a.xml new file mode 100644 index 00000000000..7b219dde263 --- /dev/null +++ b/src/bgp/testdata/routing_policy_2a.xml @@ -0,0 +1,47 @@ + + + + + + + 102 + + + + + + + 3.1.1.1 + exact + + + + reject + + + + + + 1/8 + orlonger + + + + reject + + + + + + 103 + + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_2b.xml b/src/bgp/testdata/routing_policy_2b.xml new file mode 100644 index 00000000000..15809284746 --- /dev/null +++ b/src/bgp/testdata/routing_policy_2b.xml @@ -0,0 +1,27 @@ + + + + + + + 1/8 + orlonger + + + + + + 11:13 + + + accept + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_2c.xml b/src/bgp/testdata/routing_policy_2c.xml new file mode 100644 index 00000000000..611d08a9f59 --- /dev/null +++ b/src/bgp/testdata/routing_policy_2c.xml @@ -0,0 +1,27 @@ + + + + + + + 1/8 + orlonger + + + + + + 11:13 + + + accept + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_2d.xml b/src/bgp/testdata/routing_policy_2d.xml new file mode 100644 index 00000000000..5c010b5a2f9 --- /dev/null +++ b/src/bgp/testdata/routing_policy_2d.xml @@ -0,0 +1,31 @@ + + + + + + + 1/8 + orlonger + + + + + + + 11:22 + 22:44 + 44:88 + + + + accept + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_2e.xml b/src/bgp/testdata/routing_policy_2e.xml new file mode 100644 index 00000000000..506fbcc4471 --- /dev/null +++ b/src/bgp/testdata/routing_policy_2e.xml @@ -0,0 +1,31 @@ + + + + + + + 1/8 + orlonger + + + + + + + 11:22 + 22:44 + 44:88 + + + + accept + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_2f.xml b/src/bgp/testdata/routing_policy_2f.xml new file mode 100644 index 00000000000..0f2c7f31faa --- /dev/null +++ b/src/bgp/testdata/routing_policy_2f.xml @@ -0,0 +1,31 @@ + + + + + + + 1/8 + orlonger + + + + + + + 11:22 + 22:44 + 44:88 + + + + accept + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_2g.xml b/src/bgp/testdata/routing_policy_2g.xml new file mode 100644 index 00000000000..a2a9fa753d7 --- /dev/null +++ b/src/bgp/testdata/routing_policy_2g.xml @@ -0,0 +1,32 @@ + + + + + + + 1/8 + orlonger + + + + + + + 11:22 + + + 22:44 + + + + accept + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_5.xml b/src/bgp/testdata/routing_policy_5.xml new file mode 100644 index 00000000000..3bdd5069d6b --- /dev/null +++ b/src/bgp/testdata/routing_policy_5.xml @@ -0,0 +1,31 @@ + + + + + + + 1/8 + longer + + + + + + + 11:22 + 22:44 + 44:88 + + + + accept + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_5a.xml b/src/bgp/testdata/routing_policy_5a.xml new file mode 100644 index 00000000000..dd3e1251038 --- /dev/null +++ b/src/bgp/testdata/routing_policy_5a.xml @@ -0,0 +1,31 @@ + + + + + + + 1.1.1.1/32 + exact + + + + + + + 11:22 + 22:44 + 44:88 + + + + accept + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_5b.xml b/src/bgp/testdata/routing_policy_5b.xml new file mode 100644 index 00000000000..64d3ffbb388 --- /dev/null +++ b/src/bgp/testdata/routing_policy_5b.xml @@ -0,0 +1,32 @@ + + + + + + + + 1.1.0.0/16 + exact + + + + + + + 11:22 + 22:44 + 44:88 + + + + accept + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_6.xml b/src/bgp/testdata/routing_policy_6.xml new file mode 100644 index 00000000000..3adcfb4b933 --- /dev/null +++ b/src/bgp/testdata/routing_policy_6.xml @@ -0,0 +1,53 @@ + + + + + + + 1.1.1.1/32 + exact + + + + + + 11:22 + + + + + + + 11:13 + + + + + 22:44 + + + + + + + + 1.1.0.0/16 + longer + + + + + + 44:88 + + + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_6a.xml b/src/bgp/testdata/routing_policy_6a.xml new file mode 100644 index 00000000000..7934c3d70f2 --- /dev/null +++ b/src/bgp/testdata/routing_policy_6a.xml @@ -0,0 +1,50 @@ + + + + + + + 1.1.1.1/32 + exact + + + + + + 11:22 + + + + + + + 11:22 + + + + + 22:44 + + + + + + + 22:44 + + + + + 44:88 + + + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_6b.xml b/src/bgp/testdata/routing_policy_6b.xml new file mode 100644 index 00000000000..ae9adeac1ab --- /dev/null +++ b/src/bgp/testdata/routing_policy_6b.xml @@ -0,0 +1,34 @@ + + + + + + + 1.1.1.1/32 + exact + + + + + + 11:22 + + + + + + + 11:22 + + + reject + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_7.xml b/src/bgp/testdata/routing_policy_7.xml new file mode 100644 index 00000000000..9144445d542 --- /dev/null +++ b/src/bgp/testdata/routing_policy_7.xml @@ -0,0 +1,26 @@ + + + + + + + 2001:db8:85a3::8a2e:370:7334/128 + exact + + + + + + 11:22 + + + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_7a.xml b/src/bgp/testdata/routing_policy_7a.xml new file mode 100644 index 00000000000..d0d9c73bd64 --- /dev/null +++ b/src/bgp/testdata/routing_policy_7a.xml @@ -0,0 +1,26 @@ + + + + + + + 1.1.1.1/32 + exact + + + + + + 11:22 + + + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_7b.xml b/src/bgp/testdata/routing_policy_7b.xml new file mode 100644 index 00000000000..1741aff6622 --- /dev/null +++ b/src/bgp/testdata/routing_policy_7b.xml @@ -0,0 +1,41 @@ + + + + + + + 1.1.1.1/32 + exact + + + + + + 11:22 + + + + + + + + 2001:db8:85a3::8a2e:370:7334/128 + exact + + + + + + 11:22 + + + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_7c.xml b/src/bgp/testdata/routing_policy_7c.xml new file mode 100644 index 00000000000..ee760d3e483 --- /dev/null +++ b/src/bgp/testdata/routing_policy_7c.xml @@ -0,0 +1,27 @@ + + + + + + + 2001:db8:85a3::8a2e:370:7334/128 + exact + + 11:13 + + + + + 11:22 + + + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_7d.xml b/src/bgp/testdata/routing_policy_7d.xml new file mode 100644 index 00000000000..fac6bc07f96 --- /dev/null +++ b/src/bgp/testdata/routing_policy_7d.xml @@ -0,0 +1,28 @@ + + + + + + + 2001:db8:85a3::8a2e:370:7334/128 + exact + + 11:13 + + + + + 11:22 + + 999 + + + + + + + 1.0 + + target:1:103 + + diff --git a/src/bgp/testdata/routing_policy_7e.xml b/src/bgp/testdata/routing_policy_7e.xml new file mode 100644 index 00000000000..0cffb87d6be --- /dev/null +++ b/src/bgp/testdata/routing_policy_7e.xml @@ -0,0 +1,26 @@ + + + + + + + 2001:db8:85a3::/64 + longer + + + + + + 33:66 + + + + + + + + 1.0 + + target:1:103 + +