OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
routing_policy_match.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
3  */
4 
6 
7 #include <boost/foreach.hpp>
8 #include <boost/assign/list_of.hpp>
9 
10 #include <algorithm>
11 #include <map>
12 #include <sstream>
13 #include <vector>
14 
15 #include "bgp/ipeer.h"
16 #include "bgp/bgp_attr.h"
17 #include "bgp/bgp_path.h"
35 #include "net/community_type.h"
36 
37 
38 using contrail::regex;
41 using std::includes;
42 using std::map;
43 using std::ostringstream;
44 using std::sort;
45 using std::string;
46 using std::unique;
47 using std::vector;
48 using std::find;
49 
50 MatchCommunity::MatchCommunity(const vector<string> &communities,
51  bool match_all) : match_all_(match_all) {
52  // Assume that the each community string that doesn't correspond to a
53  // community name or value is a regex string.
54  BOOST_FOREACH(const string &community, communities) {
55  uint32_t value = CommunityType::CommunityFromString(community);
56  if (value) {
57  to_match_.insert(value);
58  } else {
59  to_match_regex_strings_.push_back(community);
60  }
61  }
62 
63  // Sort and uniquify the vector of regex strings.
65  vector<string>::iterator it =
66  unique(to_match_regex_strings_.begin(), to_match_regex_strings_.end());
68 
69  // Build a vector of regexs corresponding to the regex strings.
70  BOOST_FOREACH(string regex_str, regex_strings()) {
71  to_match_regexs_.push_back(regex(regex_str));
72  }
73 }
74 
76 }
77 
78 //
79 // Return true if all community strings (normal or regex) are matched by the
80 // community values in the BgpAttr.
81 //
82 bool MatchCommunity::MatchAll(const BgpAttr *attr) const {
83  // Bail if there's no community values in the BgpAttr.
84  const Community *comm = attr->community();
85  if (!comm)
86  return false;
87 
88  // Make sure that all non-regex communities in this MatchCommunity are
89  // present in the BgpAttr.
90  vector<uint32_t> list = comm->communities();
91  sort(list.begin(), list.end());
92  if (!includes(list.begin(), list.end(),
93  communities().begin(), communities().end())) {
94  return false;
95  }
96 
97  // Make sure that each regex in this MatchCommunity is matched by one
98  // of the communities in the BgpAttr.
99  BOOST_FOREACH(const regex &match_expr, regexs()) {
100  bool matched = false;
101  BOOST_FOREACH(uint32_t community, comm->communities()) {
102  string community_str = CommunityType::CommunityToString(community);
103  if (regex_match(community_str, match_expr)) {
104  matched = true;
105  break;
106  }
107  }
108  if (!matched)
109  return false;
110  }
111 
112  return true;
113 }
114 
115 //
116 // Return true if any community strings (normal or regex) is matched by the
117 // community values in the BgpAttr.
118 //
119 bool MatchCommunity::MatchAny(const BgpAttr *attr) const {
120  // Bail if there's no community values in the BgpAttr.
121  const Community *comm = attr->community();
122  if (!comm)
123  return false;
124 
125  // Check if any of the community values in the BgpAttr matches one of
126  // the normal community strings.
127  BOOST_FOREACH(uint32_t community, comm->communities()) {
128  if (communities().find(community) != communities().end())
129  return true;
130  }
131 
132  // Check if any of the community values in the BgpAttr matches one of
133  // the community regexs.
134  BOOST_FOREACH(uint32_t community, comm->communities()) {
135  string community_str = CommunityType::CommunityToString(community);
136  BOOST_FOREACH(const regex &match_expr, regexs()) {
137  if (regex_match(community_str, match_expr))
138  return true;
139  }
140  }
141 
142  return false;
143 }
144 
145 //
146 // Return true if the BgpPath matches this MatchCommunity.
147 //
148 bool MatchCommunity::Match(const BgpRoute *route, const BgpPath *path,
149  const BgpAttr *attr) const {
150  return (match_all_ ? MatchAll(attr) : MatchAny(attr));
151 }
152 
153 //
154 // Return string representation of this MatchCommunity.
155 //
156 string MatchCommunity::ToString() const {
157  ostringstream oss;
158  if (match_all_) {
159  oss << "community (all) [ ";
160  } else {
161  oss << "community (any) [ ";
162  }
163  BOOST_FOREACH(uint32_t community, communities()) {
164  string name = CommunityType::CommunityToString(community);
165  oss << name << ",";
166  }
167  BOOST_FOREACH(string regex_str, regex_strings()) {
168  oss << regex_str << ",";
169  }
170  oss.seekp(-1, oss.cur);
171  oss << " ]";
172  return oss.str();
173 }
174 
175 //
176 // Return true if this MatchCommunity is equal to the one supplied.
177 //
178 bool MatchCommunity::IsEqual(const RoutingPolicyMatch &community) const {
179  const MatchCommunity in_community =
180  static_cast<const MatchCommunity &>(community);
181  if (match_all() != in_community.match_all())
182  return false;
183  if (communities() != in_community.communities())
184  return false;
185  if (regex_strings() != in_community.regex_strings())
186  return false;
187  return true;
188 }
189 
190 MatchExtCommunity::MatchExtCommunity(const vector<string> &communities,
191  bool match_all) : match_all_(match_all) {
192  // Assume that the each community string that doesn't correspond to a
193  // community name or value is a regex string.
194  BOOST_FOREACH(const string &community, communities) {
195  const ExtCommunity::ExtCommunityList list =
197  if (list.size()) {
198  if(!Find(list[0]))
199  to_match_.push_back(list[0]);
200  } else {
201  to_match_regex_strings_.push_back(community);
202  }
203  }
204 
205  // Sort and uniquify the vector of regex strings.
206  sort(to_match_.begin(), to_match_.end());
208  vector<string>::iterator it =
209  unique(to_match_regex_strings_.begin(), to_match_regex_strings_.end());
211 
212  // Build a vector of regexs corresponding to the regex strings.
213  BOOST_FOREACH(string regex_str, regex_strings()) {
214  to_match_regexs_.push_back(regex(regex_str));
215  }
216 }
217 
219 }
220 
221 //
222 // Return true if all community strings (normal or regex) are matched by the
223 // community values in the BgpAttr.
224 //
225 bool MatchExtCommunity::MatchAll(const BgpAttr *attr) const {
226  // Bail if there's no community values in the BgpAttr.
227  const ExtCommunity *comm = attr->ext_community();
228  if (!comm)
229  return false;
230 
231  // Make sure that all non-regex communities in this MatchExtCommunity are
232  // present in the BgpAttr.
234  sort(list.begin(), list.end());
235  if (!includes(list.begin(), list.end(),
236  communities().begin(), communities().end())) {
237  return false;
238  }
239 
240  // Make sure that each regex in this MatchExtCommunity is matched by one
241  // of the communities in the BgpAttr.
242  BOOST_FOREACH(const regex &match_expr, regexs()) {
243  bool matched = false;
244  BOOST_FOREACH(ExtCommunity::ExtCommunityValue community,
245  comm->communities()) {
246  string community_str = ExtCommunity::ToString(community);
247  if (regex_match(community_str, match_expr)) {
248  matched = true;
249  break;
250  }
251  community_str = ExtCommunity::ToHexString(community);
252  if (regex_match(community_str, match_expr)) {
253  matched = true;
254  break;
255  }
256  }
257  if (!matched)
258  return false;
259  }
260 
261  return true;
262 }
263 
265  const {
266  return (std::find(communities().begin(), communities().end(), community) !=
267  communities().end());
268 }
269 
270 //
271 // Return true if any community strings (normal or regex) is matched by the
272 // community values in the BgpAttr.
273 //
274 bool MatchExtCommunity::MatchAny(const BgpAttr *attr) const {
275  // Bail if there's no community values in the BgpAttr.
276  const ExtCommunity *comm = attr->ext_community();
277  if (!comm)
278  return false;
279 
280  // Check if any of the community values in the BgpAttr matches one of
281  // the normal community strings.
282  BOOST_FOREACH(ExtCommunity::ExtCommunityValue community,
283  comm->communities()) {
284  if (Find(community))
285  return true;
286  }
287 
288  // Check if any of the community values in the BgpAttr matches one of
289  // the community regexs.
290  BOOST_FOREACH(ExtCommunity::ExtCommunityValue community,
291  comm->communities()) {
292  string community_str = ExtCommunity::ToString(community);
293  BOOST_FOREACH(const regex &match_expr, regexs()) {
294  if (regex_match(community_str, match_expr))
295  return true;
296  }
297  community_str = ExtCommunity::ToHexString(community);
298  BOOST_FOREACH(const regex &match_expr, regexs()) {
299  if (regex_match(community_str, match_expr))
300  return true;
301  }
302  }
303 
304  return false;
305 }
306 
307 //
308 // Return true if the BgpPath matches this MatchExtCommunity.
309 //
310 bool MatchExtCommunity::Match(const BgpRoute *route, const BgpPath *path,
311  const BgpAttr *attr) const {
312  return (match_all_ ? MatchAll(attr) : MatchAny(attr));
313 }
314 
315 //
316 // Return string representation of this MatchExtCommunity.
317 //
319  ostringstream oss;
320  if (match_all_) {
321  oss << "Extcommunity (all) [ ";
322  } else {
323  oss << "Extcommunity (any) [ ";
324  }
325  BOOST_FOREACH(ExtCommunity::ExtCommunityValue community, communities()) {
326  string name = ExtCommunity::ToString(community);
327  oss << name << ",";
328  }
329  BOOST_FOREACH(string regex_str, regex_strings()) {
330  oss << regex_str << ",";
331  }
332  oss.seekp(-1, oss.cur);
333  oss << " ]";
334  return oss.str();
335 }
336 
337 //
338 // Return true if this MatchExtCommunity is equal to the one supplied.
339 //
340 bool MatchExtCommunity::IsEqual(const RoutingPolicyMatch &community) const {
341  const MatchExtCommunity in_community =
342  static_cast<const MatchExtCommunity &>(community);
343  if (match_all() != in_community.match_all())
344  return false;
345  if (communities() != in_community.communities())
346  return false;
347  if (regex_strings() != in_community.regex_strings())
348  return false;
349  return true;
350 }
351 
352 template <typename T>
354  const string &match_type_str) {
355  MatchType match_type = EXACT;
356  if (match_type_str == "exact") {
357  match_type = EXACT;
358  } else if (match_type_str == "longer") {
359  match_type = LONGER;
360  } else if (match_type_str == "orlonger") {
361  match_type = ORLONGER;
362  }
363  return match_type;
364 }
365 
366 template <typename T>
368  BOOST_FOREACH(const PrefixMatchConfig &match_config, match_config_list) {
369  boost::system::error_code ec;
370  PrefixT prefix = PrefixT::FromString(match_config.prefix_to_match, &ec);
371  MatchType match_type =
373  match_list_.push_back(PrefixMatch(prefix, match_type));
374  }
375 
376  // Sort and uniquify the vector of PrefixMatch elements.
377  sort(match_list_.begin(), match_list_.end());
378  typename PrefixMatchList::iterator it =
379  unique(match_list_.begin(), match_list_.end());
380  match_list_.erase(it, match_list_.end());
381 }
382 
383 template <typename T>
385 }
386 
387 template <typename T>
388 bool MatchPrefix<T>::Match(const BgpRoute *route, const BgpPath *path,
389  const BgpAttr *attr) const {
390  const RouteT *in_route = dynamic_cast<const RouteT *>(route);
391  if (in_route == NULL)
392  return false;
393  const PrefixT &prefix = in_route->GetPrefix();
394  BOOST_FOREACH(const PrefixMatch &prefix_match, match_list_) {
395  if (prefix_match.match_type == EXACT) {
396  if (prefix == prefix_match.prefix)
397  return true;
398  } else if (prefix_match.match_type == LONGER) {
399  if (prefix == prefix_match.prefix)
400  continue;
401  if (prefix.IsMoreSpecific(prefix_match.prefix))
402  return true;
403  } else if (prefix_match.match_type == ORLONGER) {
404  if (prefix.IsMoreSpecific(prefix_match.prefix))
405  return true;
406  }
407  }
408  return false;
409 }
410 
411 template <typename T>
412 bool MatchPrefix<T>::IsEqual(const RoutingPolicyMatch &prefix) const {
413  const MatchPrefix in_prefix = static_cast<const MatchPrefix&>(prefix);
414  return (in_prefix.match_list_ == match_list_);
415 }
416 
417 template <typename T>
418 string MatchPrefix<T>::ToString() const {
419  ostringstream oss;
420  oss << "prefix [";
421  BOOST_FOREACH(const PrefixMatch &prefix_match, match_list_) {
422  oss << " " << prefix_match.prefix.ToString();
423  if (prefix_match.match_type == LONGER) {
424  oss << " longer";
425  } else if (prefix_match.match_type == ORLONGER) {
426  oss << " orlonger";
427  }
428  oss << ",";
429  }
430  oss.seekp(-1, oss.cur);
431  oss << " ]";
432  return oss.str();
433 }
434 
435 template class MatchPrefix<PrefixMatchInet>;
436 template class MatchPrefix<PrefixMatchInet6>;
437 
438 static const map<string, MatchProtocol::MatchProtocolType> fromString
439  = boost::assign::map_list_of
440  ("bgp", MatchProtocol::BGP)
441  ("xmpp", MatchProtocol::XMPP)
442  ("static", MatchProtocol::StaticRoute)
443  ("service-chain", MatchProtocol::ServiceChainRoute)
444  ("aggregate", MatchProtocol::AggregateRoute)
445  ("interface", MatchProtocol::Interface)
446  ("interface-static", MatchProtocol::InterfaceStatic)
447  ("service-interface", MatchProtocol::ServiceInterface)
448  ("bgpaas", MatchProtocol::BGPaaS);
449 
450 static const map<MatchProtocol::MatchProtocolType, string> toString
451  = boost::assign::map_list_of
452  (MatchProtocol::BGP, "bgp")
453  (MatchProtocol::XMPP, "xmpp")
454  (MatchProtocol::StaticRoute, "static")
455  (MatchProtocol::ServiceChainRoute, "service-chain")
456  (MatchProtocol::AggregateRoute, "aggregate")
457  (MatchProtocol::Interface, "interface")
458  (MatchProtocol::InterfaceStatic, "interface-static")
459  (MatchProtocol::ServiceInterface, "service-interface")
460  (MatchProtocol::BGPaaS, "bgpaas");
461 
462 static const map<MatchProtocol::MatchProtocolType, BgpPath::PathSource>
463  pathSourceMap = boost::assign::map_list_of
473 
474 static const vector<MatchProtocol::MatchProtocolType>
475  isSubprotocol = boost::assign::list_of(MatchProtocol::Interface)
479 
481  return (find(isSubprotocol.begin(), isSubprotocol.end(), protocol) !=
482  isSubprotocol.end());
483 }
484 
486  map<MatchProtocol::MatchProtocolType, string>::const_iterator it =
487  toString.find(protocol);
488  if (it != toString.end()) {
489  return it->second;
490  }
491  return "unspecified";
492 }
493 
495  const string &protocol) {
496  map<string, MatchProtocol::MatchProtocolType>::const_iterator it =
497  fromString.find(protocol);
498  if (it != fromString.end()) {
499  return it->second;
500  }
502 }
503 
506  map<MatchProtocol::MatchProtocolType, BgpPath::PathSource>::const_iterator
507  it = pathSourceMap.find(src);
508  if (it != pathSourceMap.end()) {
509  return it->second;
510  }
511  return BgpPath::None;
512 }
513 
514 MatchProtocol::MatchProtocol(const vector<string> &protocols) {
515  BOOST_FOREACH(const string &protocol, protocols) {
516  MatchProtocolType value = MatchProtocolFromString(protocol);
517  // Ignore invalid protocol values.
518  if (value == Unspecified)
519  continue;
520  to_match_.push_back(value);
521  }
522 
523  // Sort and uniquify the vector match protocols.
524  sort(to_match_.begin(), to_match_.end());
525  vector<MatchProtocolType>::iterator it =
526  unique(to_match_.begin(), to_match_.end());
527  to_match_.erase(it, to_match_.end());
528 }
529 
531 }
532 
533 bool MatchProtocol::Match(const BgpRoute *route, const BgpPath *path,
534  const BgpAttr *attr) const {
535  BgpPath::PathSource path_src = path->GetSource();
536  bool is_xmpp = path->GetPeer() ? path->GetPeer()->IsXmppPeer() : false;
537  bool bgpaas = path->GetPeer() ? path->GetPeer()->IsRouterTypeBGPaaS() : false;
538  BOOST_FOREACH(MatchProtocolType protocol, protocols()) {
539  if (IsSubprotocol(protocol)) {
540  // Check only if matching protocol is subprotocol
541  if (attr && !attr->sub_protocol().empty()) {
542  std::string matchps = MatchProtocolToString(protocol);
543  if (matchps.compare(attr->sub_protocol()) == 0)
544  return true;
545  }
546  } else {
547  BgpPath::PathSource mapped_src =
548  PathSourceFromMatchProtocol(protocol);
549  if (mapped_src != BgpPath::None) {
550  if (mapped_src == path_src) {
551  if (protocol == XMPP && !is_xmpp)
552  continue;
553  if (protocol == BGP && (bgpaas || is_xmpp))
554  continue;
555  if (protocol == BGPaaS && (!bgpaas || is_xmpp))
556  continue;
557  return true;
558  }
559  }
560  }
561  }
562  return false;
563 }
564 
565 string MatchProtocol::ToString() const {
566  ostringstream oss;
567  oss << "protocol [ ";
568  BOOST_FOREACH(MatchProtocolType protocol, protocols()) {
569  string name = MatchProtocolToString(protocol);
570  oss << name << ",";
571  }
572  oss.seekp(-1, oss.cur);
573  oss << " ]";
574  return oss.str();
575 }
576 
577 bool MatchProtocol::IsEqual(const RoutingPolicyMatch &protocol) const {
578  const MatchProtocol in_protocol =
579  static_cast<const MatchProtocol&>(protocol);
580  return (protocols() == in_protocol.protocols());
581 }
const Community * community() const
Definition: bgp_attr.h:914
const std::vector< uint32_t > & communities() const
Definition: community.h:65
virtual bool IsEqual(const RoutingPolicyMatch &community) const
bool Find(const ExtCommunity::ExtCommunityValue &community) const
virtual bool IsEqual(const RoutingPolicyMatch &community) const
boost::array< uint8_t, 8 > ExtCommunityValue
Definition: community.h:152
bool match_all() const
static const map< string, MatchProtocol::MatchProtocolType > fromString
virtual std::string ToString() const
virtual bool IsXmppPeer() const =0
CommunityRegexList to_match_regexs_
virtual bool Match(const BgpRoute *route, const BgpPath *path, const BgpAttr *attr) const
bool MatchAny(const BgpAttr *attr) const
static const map< MatchProtocol::MatchProtocolType, string > toString
static std::string ToHexString(const ExtCommunityValue &val)
Definition: community.cc:352
static const std::string CommunityToString(uint32_t comm)
PathSourceList to_match_
static MatchProtocol::MatchProtocolType MatchProtocolFromString(const string &protocol)
static const vector< MatchProtocol::MatchProtocolType > isSubprotocol
virtual bool Match(const BgpRoute *route, const BgpPath *path, const BgpAttr *attr) const
virtual bool IsRouterTypeBGPaaS() const =0
virtual bool Match(const BgpRoute *route, const BgpPath *path, const BgpAttr *attr) const
MatchExtCommunity(const std::vector< std::string > &communities, bool match_all)
const CommunityList & communities() const
MatchProtocol(const std::vector< std::string > &protocols)
std::string prefix_to_match
Definition: bgp_config.h:354
virtual bool Match(const BgpRoute *route, const BgpPath *path, const BgpAttr *attr) const
virtual std::string ToString() const
const CommunityRegexList & regexs() const
virtual std::string ToString() const
static bool regex_match(const std::string &input, const regex &regex)
Definition: regex.h:34
bool MatchAny(const BgpAttr *attr) const
const std::string & sub_protocol() const
Definition: bgp_attr.h:927
PathSource
Definition: bgp_path.h:37
virtual std::string ToString() const
const CommunityRegexStringList & regex_strings() const
CommunityRegexList to_match_regexs_
PathSource GetSource() const
Definition: bgp_path.h:103
const CommunityRegexList & regexs() const
virtual bool IsEqual(const RoutingPolicyMatch &community) const
const ExtCommunityList & communities() const
Definition: community.h:180
std::vector< PrefixMatchConfig > PrefixMatchConfigList
Definition: bgp_config.h:358
static BgpPath::PathSource PathSourceFromMatchProtocol(MatchProtocol::MatchProtocolType src)
std::string prefix_match_type
Definition: bgp_config.h:355
PrefixMatchList match_list_
static ExtCommunityList ExtCommunityFromString(const std::string &comm)
Definition: community.cc:305
const string MatchProtocolToString(MatchProtocol::MatchProtocolType protocol)
IPeer * GetPeer()
Definition: bgp_path.h:76
static bool IsSubprotocol(MatchProtocol::MatchProtocolType protocol)
static std::string ToString(const ExtCommunityValue &val)
Definition: community.cc:361
static bool regex_search(const std::string &input, const regex &regex)
Definition: regex.h:25
const PathSourceList & protocols() const
CommunityList to_match_
const ExtCommunity * ext_community() const
Definition: bgp_attr.h:915
const CommunityRegexStringList & regex_strings() const
std::vector< ExtCommunityValue > ExtCommunityList
Definition: community.h:153
virtual bool IsEqual(const RoutingPolicyMatch &prefix) const
CommunityRegexStringList to_match_regex_strings_
static const map< MatchProtocol::MatchProtocolType, BgpPath::PathSource > pathSourceMap
MatchPrefix(const PrefixMatchConfigList &match_config_list)
bool MatchAll(const BgpAttr *attr) const
ExtCommunity::ExtCommunityList to_match_
MatchCommunity(const std::vector< std::string > &communities, bool match_all)
static uint32_t CommunityFromString(const std::string &comm, boost::system::error_code *perr=NULL)
static PhysicalDevice::ManagementProtocol FromString(const string &proto)
bool MatchAll(const BgpAttr *attr) const
const ExtCommunity::ExtCommunityList & communities() const
CommunityRegexStringList to_match_regex_strings_
static MatchType GetMatchType(const std::string &match_type_str)