Skip to content

Commit

Permalink
Add path source as match condition
Browse files Browse the repository at this point in the history
    1. control-node changes
    2. Unit tests for matching protocols

Change-Id: I406f20762498be79c43ec2c8d2dde46af1c55467
Related-bug: #1500698
  • Loading branch information
bailkeri committed Jan 29, 2016
1 parent b1b4ea3 commit e8c489d
Show file tree
Hide file tree
Showing 13 changed files with 457 additions and 22 deletions.
8 changes: 8 additions & 0 deletions src/bgp/bgp_config.cc
Expand Up @@ -330,6 +330,14 @@ void BgpRoutingPolicyConfig::Clear() {
std::string RoutingPolicyMatchConfig::ToString() const {
ostringstream oss;
oss << "from {" << std::endl;
if (!protocols_match.empty()) {
oss << " protocol [ ";
BOOST_FOREACH(const string &protocol, protocols_match) {
oss << protocol << ",";
}
oss.seekp(-1, oss.cur);
oss << " ]";
}
if (!community_match.empty()) {
oss << " community " << community_match << std::endl;
}
Expand Down
2 changes: 2 additions & 0 deletions src/bgp/bgp_config.h
Expand Up @@ -298,6 +298,7 @@ struct StaticRouteConfig {
};

typedef std::vector<std::string> CommunityList;
typedef std::vector<std::string> ProtocolList;

struct PrefixMatchConfig {
std::string prefix_to_match;
Expand All @@ -307,6 +308,7 @@ struct PrefixMatchConfig {
typedef std::vector<PrefixMatchConfig> PrefixMatchConfigList;

struct RoutingPolicyMatchConfig {
ProtocolList protocols_match;
std::string community_match;
PrefixMatchConfigList prefixes_to_match;
std::string ToString() const;
Expand Down
1 change: 1 addition & 0 deletions src/bgp/bgp_config_ifmap.cc
Expand Up @@ -1569,6 +1569,7 @@ void BgpIfmapRoutingPolicyConfig::RemoveInstance(BgpIfmapInstanceConfig *rti) {

static void BuildPolicyTerm(autogen::PolicyTerm cfg_term,
RoutingPolicyTerm *term) {
term->match.protocols_match = cfg_term.fromxx.protocol;
term->match.community_match = cfg_term.fromxx.community;
BOOST_FOREACH(const autogen::PrefixMatch &prefix_match,
cfg_term.fromxx.prefix) {
Expand Down
3 changes: 2 additions & 1 deletion src/bgp/routing-instance/routing_instance.cc
Expand Up @@ -1175,7 +1175,8 @@ bool RoutingInstance::ProcessRoutingPolicy(const BgpRoute *route,
// Update of the attribute based on routing policy action is done
// on the snapshot of original attribute passed to this function
RoutingPolicy::PolicyResult result =
policy_mgr->ExecuteRoutingPolicy(policy.get(), route, out_attr);
policy_mgr->ExecuteRoutingPolicy(policy.get(), route,
path, out_attr);
if (result.first) {
// Hit a terminal policy
if (!result.second) {
Expand Down
19 changes: 13 additions & 6 deletions src/bgp/routing-policy/routing_policy.cc
Expand Up @@ -153,8 +153,8 @@ void RoutingPolicyMgr::ApplyRoutingPolicy(RoutingInstance *instance) {
// On a given path of the route, apply the policy
RoutingPolicy::PolicyResult RoutingPolicyMgr::ExecuteRoutingPolicy(
const RoutingPolicy *policy, const BgpRoute *route,
BgpAttr *attr) const {
return (*policy)(route, attr);
const BgpPath *path, BgpAttr *attr) const {
return (*policy)(route, path, attr);
}

//
Expand Down Expand Up @@ -359,6 +359,12 @@ RoutingPolicy::PolicyTermPtr RoutingPolicy::BuildTerm(const RoutingPolicyTerm &c
matches.push_back(community);
}

if (!cfg_term.match.protocols_match.empty()) {
MatchProtocol *protocol =
new MatchProtocol(cfg_term.match.protocols_match);
matches.push_back(protocol);
}

if (!cfg_term.match.prefixes_to_match.empty()) {
PrefixMatchConfigList inet_prefix_list;
PrefixMatchConfigList inet6_prefix_list;
Expand Down Expand Up @@ -529,10 +535,10 @@ void RoutingPolicy::RetryDelete() {
}

RoutingPolicy::PolicyResult RoutingPolicy::operator()(const BgpRoute *route,
BgpAttr *attr) const {
const BgpPath *path, BgpAttr *attr) const {
BOOST_FOREACH(PolicyTermPtr term, terms()) {
bool terminal = term->terminal();
bool matched = term->ApplyTerm(route, attr);
bool matched = term->ApplyTerm(route, path, attr);
if (matched && terminal) {
return std::make_pair(terminal,
(*term->actions().begin())->accept());
Expand All @@ -555,10 +561,11 @@ bool PolicyTerm::terminal() const {
return false;
}

bool PolicyTerm::ApplyTerm(const BgpRoute *route, BgpAttr *attr) const {
bool PolicyTerm::ApplyTerm(const BgpRoute *route, const BgpPath *path,
BgpAttr *attr) const {
bool matched = true;
BOOST_FOREACH(RoutingPolicyMatch *match, matches()) {
if (!(*match)(route, attr)) {
if (!(*match)(route, path, attr)) {
matched = false;
break;
}
Expand Down
9 changes: 6 additions & 3 deletions src/bgp/routing-policy/routing_policy.h
Expand Up @@ -20,6 +20,7 @@
#include <sandesh/sandesh_trace.h>

class BgpAttr;
class BgpPath;
class BgpRoute;
class BgpServer;
class BgpTable;
Expand Down Expand Up @@ -200,7 +201,8 @@ class PolicyTerm {
PolicyTerm();
~PolicyTerm();
bool terminal() const;
bool ApplyTerm(const BgpRoute *route, BgpAttr *attr) const;
bool ApplyTerm(const BgpRoute *route,
const BgpPath *path, BgpAttr *attr) const;
void set_actions(const ActionList &actions) {
actions_ = actions;
}
Expand Down Expand Up @@ -253,7 +255,8 @@ class RoutingPolicy {
terms_.push_back(term);
}

PolicyResult operator()(const BgpRoute *route, BgpAttr *attr) const;
PolicyResult operator()(const BgpRoute *route,
const BgpPath *path, BgpAttr *attr) const;
uint32_t generation() const { return generation_; }
uint32_t refcount() const { return refcount_; }

Expand Down Expand Up @@ -373,7 +376,7 @@ class RoutingPolicyMgr {
LifetimeActor *deleter();

RoutingPolicy::PolicyResult ExecuteRoutingPolicy(const RoutingPolicy *policy,
const BgpRoute *route, BgpAttr *attr) const;
const BgpRoute *route, const BgpPath *path, BgpAttr *attr) const;


// Update the routing policy list on attach point
Expand Down
122 changes: 115 additions & 7 deletions src/bgp/routing-policy/routing_policy_match.cc
Expand Up @@ -5,18 +5,24 @@
#include "bgp/routing-policy/routing_policy_match.h"

#include <boost/foreach.hpp>
#include <boost/assign/list_of.hpp>

#include <algorithm>
#include <map>
#include <sstream>
#include <vector>

#include <bgp/bgp_attr.h>
#include <bgp/bgp_path.h>
#include <net/community_type.h>

using std::ostringstream;
using std::string;
using std::make_pair;
using std::vector;
using std::map;

MatchCommunity::MatchCommunity(const std::vector<string> &communities) {
MatchCommunity::MatchCommunity(const vector<string> &communities) {
BOOST_FOREACH(const string &community, communities) {
uint32_t value = CommunityType::CommunityFromString(community);
// Invalid community from config is ignored
Expand All @@ -26,19 +32,19 @@ MatchCommunity::MatchCommunity(const std::vector<string> &communities) {
}

std::sort(to_match_.begin(), to_match_.end());
std::vector<uint32_t>::iterator it =
vector<uint32_t>::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 {
bool MatchCommunity::Match(const BgpRoute *route, const BgpPath *path,
const BgpAttr *attr) const {
const Community *comm = attr->community();
if (comm) {
std::vector<uint32_t> list = comm->communities();
vector<uint32_t> list = comm->communities();
if (list.size() < to_match_.size()) return false;
std::sort(list.begin(), list.end());
if (std::includes(list.begin(), list.end(),
Expand Down Expand Up @@ -88,8 +94,8 @@ MatchPrefix<T>::~MatchPrefix() {
}

template <typename T>
bool MatchPrefix<T>::Match(const BgpRoute *route,
const BgpAttr *attr) const {
bool MatchPrefix<T>::Match(const BgpRoute *route, const BgpPath *path,
const BgpAttr *attr) const {
const RouteT *in_route = dynamic_cast<const RouteT *>(route);
if (in_route == NULL) return false;
const PrefixT &prefix = in_route->GetPrefix();
Expand Down Expand Up @@ -132,3 +138,105 @@ string MatchPrefix<T>::ToString() const {

template class MatchPrefix<InetPrefixMatch>;
template class MatchPrefix<Inet6PrefixMatch>;

static const map<string, MatchProtocol::MatchProtocolType> fromString
= boost::assign::map_list_of
("bgp", MatchProtocol::BGP)
("xmpp", MatchProtocol::XMPP)
("static", MatchProtocol::StaticRoute)
("service-chain", MatchProtocol::ServiceChainRoute)
("aggregate", MatchProtocol::AggregateRoute);

static const map<MatchProtocol::MatchProtocolType, string> toString
= boost::assign::map_list_of
(MatchProtocol::BGP, "bgp")
(MatchProtocol::XMPP, "xmpp")
(MatchProtocol::StaticRoute, "static")
(MatchProtocol::ServiceChainRoute, "service-chain")
(MatchProtocol::AggregateRoute, "aggregate");

static const map<MatchProtocol::MatchProtocolType, BgpPath::PathSource>
pathSourceMap = boost::assign::map_list_of
(MatchProtocol::BGP, BgpPath::BGP_XMPP)
(MatchProtocol::XMPP, BgpPath::BGP_XMPP)
(MatchProtocol::StaticRoute, BgpPath::StaticRoute)
(MatchProtocol::ServiceChainRoute, BgpPath::ServiceChain)
(MatchProtocol::AggregateRoute, BgpPath::Aggregate);

static const string MatchProtocolToString(
MatchProtocol::MatchProtocolType protocol) {
map<MatchProtocol::MatchProtocolType, string>::const_iterator it =
toString.find(protocol);
if (it != toString.end()) {
return it->second;
}
return "unspecified";
}

static MatchProtocol::MatchProtocolType MatchProtocolFromString(
const string &protocol) {
map<string, MatchProtocol::MatchProtocolType>::const_iterator it =
fromString.find(protocol);
if (it != fromString.end()) {
return it->second;
}
return MatchProtocol::Unspecified;
}

static BgpPath::PathSource PathSourceFromMatchProtocol(
MatchProtocol::MatchProtocolType src) {
map<MatchProtocol::MatchProtocolType, BgpPath::PathSource>::const_iterator
it = pathSourceMap.find(src);
if (it != pathSourceMap.end()) {
return it->second;
}
return BgpPath::None;
}

MatchProtocol::MatchProtocol(const vector<string> &protocols) {
BOOST_FOREACH(const string &protocol, protocols) {
MatchProtocolType value = MatchProtocolFromString(protocol);
// Invalid community from config is ignored
if (value != Unspecified) {
to_match_.push_back(value);
}
}
}

MatchProtocol::~MatchProtocol() {
}

bool MatchProtocol::Match(const BgpRoute *route, const BgpPath *path,
const BgpAttr *attr) const {
BgpPath::PathSource path_src = path->GetSource();
bool is_xmpp = path->GetPeer() ? path->GetPeer()->IsXmppPeer() : false;
BOOST_FOREACH(MatchProtocolType protocol, protocols()) {
BgpPath::PathSource mapped_src = PathSourceFromMatchProtocol(protocol);
if (mapped_src != BgpPath::None) {
if (mapped_src == path_src) {
if (protocol == XMPP && !is_xmpp) continue;
if (protocol == BGP && is_xmpp) continue;
return true;
}
}
}
return false;
}

string MatchProtocol::ToString() const {
ostringstream oss;
oss << "protocol [ ";
BOOST_FOREACH(MatchProtocolType protocol, protocols()) {
string name = MatchProtocolToString(protocol);
oss << name << ",";
}
oss.seekp(-1, oss.cur);
oss << " ]";
return oss.str();
}

bool MatchProtocol::IsEqual(const RoutingPolicyMatch &protocol) const {
const MatchProtocol in_protocol =
static_cast<const MatchProtocol&>(protocol);
return (protocols() == in_protocol.protocols());
}
39 changes: 34 additions & 5 deletions src/bgp/routing-policy/routing_policy_match.h
Expand Up @@ -16,6 +16,7 @@
#include "bgp/inet6/inet6_route.h"

class BgpAttr;
class BgpPath;
class BgpRoute;
class Community;

Expand All @@ -24,10 +25,12 @@ class RoutingPolicyMatch {
virtual std::string ToString() const = 0;
virtual ~RoutingPolicyMatch() {
}
bool operator()(const BgpRoute *route, const BgpAttr *attr) const {
return Match(route, attr);
bool operator()(const BgpRoute *route,
const BgpPath *path, const BgpAttr *attr) const {
return Match(route, path, attr);
}
virtual bool Match(const BgpRoute *route, const BgpAttr *attr) const = 0;
virtual bool Match(const BgpRoute *route,
const BgpPath *path, const BgpAttr *attr) const = 0;
virtual bool operator==(const RoutingPolicyMatch &match) const {
if (typeid(match) == typeid(*this))
return(IsEqual(match));
Expand All @@ -41,7 +44,8 @@ class MatchCommunity: public RoutingPolicyMatch {
typedef std::vector<uint32_t> CommunityList;
explicit MatchCommunity(const std::vector<std::string> &communities);
virtual ~MatchCommunity();
virtual bool Match(const BgpRoute *route, const BgpAttr *attr) const;
virtual bool Match(const BgpRoute *route,
const BgpPath *path, const BgpAttr *attr) const;
virtual std::string ToString() const;
virtual bool IsEqual(const RoutingPolicyMatch &community) const;
const CommunityList &communities() const {
Expand All @@ -51,6 +55,30 @@ class MatchCommunity: public RoutingPolicyMatch {
CommunityList to_match_;
};

class MatchProtocol: public RoutingPolicyMatch {
public:
enum MatchProtocolType {
Unspecified = 0,
BGP,
XMPP,
StaticRoute,
ServiceChainRoute,
AggregateRoute,
};
typedef std::vector<MatchProtocolType> PathSourceList;
explicit MatchProtocol(const std::vector<std::string> &protocols);
virtual ~MatchProtocol();
virtual bool Match(const BgpRoute *route,
const BgpPath *path, const BgpAttr *attr) const;
virtual std::string ToString() const;
virtual bool IsEqual(const RoutingPolicyMatch &community) const;
const PathSourceList &protocols() const {
return to_match_;
}
private:
PathSourceList to_match_;
};

template <typename T1, typename T2>
struct PrefixMatchBase {
typedef T1 RouteT;
Expand All @@ -77,7 +105,8 @@ class MatchPrefix : public RoutingPolicyMatch {
typedef std::vector<PrefixMatch> PrefixMatchList;
explicit MatchPrefix(const PrefixMatchConfigList &list);
virtual ~MatchPrefix();
virtual bool Match(const BgpRoute *route, const BgpAttr *attr) const;
virtual bool Match(const BgpRoute *route,
const BgpPath *path, const BgpAttr *attr) const;
virtual std::string ToString() const;
virtual bool IsEqual(const RoutingPolicyMatch &prefix) const;
private:
Expand Down

0 comments on commit e8c489d

Please sign in to comment.