From 8e1ccb6afabc7c96f1b716bd395a06154e9e7ff5 Mon Sep 17 00:00:00 2001 From: Prakash M Bailkeri Date: Mon, 30 Nov 2015 23:53:26 +0530 Subject: [PATCH] Routing policy operational code changes TODOs: 1. handle update of policy 2. Handle update of policies on routing instance 3. UT coverage 4. Comments and formatting Routing policy Unit test cases Bug fix for inet6 prefix match Change-Id: I83de4a24f52c9781d61f4325246b10e115ad8af6 Related-bug: #1500698 --- src/bgp/bgp_common.h | 5 +- src/bgp/bgp_config.h | 10 +- src/bgp/bgp_config_ifmap.cc | 36 +- src/bgp/bgp_config_listener.cc | 3 +- src/bgp/bgp_factory.cc | 1 + src/bgp/bgp_factory.h | 5 + src/bgp/bgp_path.h | 29 +- src/bgp/bgp_route.cc | 6 +- src/bgp/bgp_server.cc | 12 +- src/bgp/bgp_server.h | 4 +- src/bgp/community.cc | 63 + src/bgp/community.h | 9 + src/bgp/routing-instance/routing_instance.cc | 41 + src/bgp/routing-instance/routing_instance.h | 16 + src/bgp/routing-policy/SConscript | 5 +- src/bgp/routing-policy/routing_policy.cc | 350 ++++- src/bgp/routing-policy/routing_policy.h | 168 ++- .../routing-policy/routing_policy_action.cc | 70 + .../routing-policy/routing_policy_action.h | 87 ++ .../routing-policy/routing_policy_match.cc | 91 ++ src/bgp/routing-policy/routing_policy_match.h | 76 ++ src/bgp/test/SConscript | 4 + src/bgp/test/bgp_config_listener_test.cc | 64 +- src/bgp/test/bgp_config_test.cc | 119 +- src/bgp/test/bgp_ifmap_config_manager_test.cc | 28 +- src/bgp/test/routing_policy_test.cc | 1165 +++++++++++++++++ src/bgp/testdata/config_listener_test_14.xml | 41 + src/bgp/testdata/config_listener_test_9.xml | 8 + src/bgp/testdata/routing_policy_0.xml | 5 +- src/bgp/testdata/routing_policy_1.xml | 4 +- src/bgp/testdata/routing_policy_1a.xml | 36 + src/bgp/testdata/routing_policy_2.xml | 25 +- src/bgp/testdata/routing_policy_2a.xml | 47 + src/bgp/testdata/routing_policy_2b.xml | 27 + src/bgp/testdata/routing_policy_2c.xml | 27 + src/bgp/testdata/routing_policy_2d.xml | 31 + src/bgp/testdata/routing_policy_2e.xml | 31 + src/bgp/testdata/routing_policy_2f.xml | 31 + src/bgp/testdata/routing_policy_2g.xml | 32 + src/bgp/testdata/routing_policy_5.xml | 31 + src/bgp/testdata/routing_policy_5a.xml | 31 + src/bgp/testdata/routing_policy_5b.xml | 32 + src/bgp/testdata/routing_policy_6.xml | 53 + src/bgp/testdata/routing_policy_6a.xml | 50 + src/bgp/testdata/routing_policy_6b.xml | 34 + src/bgp/testdata/routing_policy_7.xml | 26 + src/bgp/testdata/routing_policy_7a.xml | 26 + src/bgp/testdata/routing_policy_7b.xml | 41 + src/bgp/testdata/routing_policy_7c.xml | 27 + src/bgp/testdata/routing_policy_7d.xml | 28 + src/bgp/testdata/routing_policy_7e.xml | 26 + 51 files changed, 3145 insertions(+), 72 deletions(-) create mode 100644 src/bgp/routing-policy/routing_policy_action.cc create mode 100644 src/bgp/routing-policy/routing_policy_action.h create mode 100644 src/bgp/routing-policy/routing_policy_match.cc create mode 100644 src/bgp/routing-policy/routing_policy_match.h create mode 100644 src/bgp/test/routing_policy_test.cc create mode 100644 src/bgp/testdata/config_listener_test_14.xml create mode 100644 src/bgp/testdata/routing_policy_1a.xml create mode 100644 src/bgp/testdata/routing_policy_2a.xml create mode 100644 src/bgp/testdata/routing_policy_2b.xml create mode 100644 src/bgp/testdata/routing_policy_2c.xml create mode 100644 src/bgp/testdata/routing_policy_2d.xml create mode 100644 src/bgp/testdata/routing_policy_2e.xml create mode 100644 src/bgp/testdata/routing_policy_2f.xml create mode 100644 src/bgp/testdata/routing_policy_2g.xml create mode 100644 src/bgp/testdata/routing_policy_5.xml create mode 100644 src/bgp/testdata/routing_policy_5a.xml create mode 100644 src/bgp/testdata/routing_policy_5b.xml create mode 100644 src/bgp/testdata/routing_policy_6.xml create mode 100644 src/bgp/testdata/routing_policy_6a.xml create mode 100644 src/bgp/testdata/routing_policy_6b.xml create mode 100644 src/bgp/testdata/routing_policy_7.xml create mode 100644 src/bgp/testdata/routing_policy_7a.xml create mode 100644 src/bgp/testdata/routing_policy_7b.xml create mode 100644 src/bgp/testdata/routing_policy_7c.xml create mode 100644 src/bgp/testdata/routing_policy_7d.xml create mode 100644 src/bgp/testdata/routing_policy_7e.xml 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 + +