OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bgp_path.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "bgp/bgp_path.h"
6 
7 #include <boost/foreach.hpp>
8 
9 #include "bgp/bgp_peer.h"
10 #include "bgp/bgp_route.h"
11 #include "bgp/bgp_server.h"
13 #include "net/community_type.h"
14 
15 using std::string;
16 using std::vector;
17 
18 string BgpPath::PathIdString(uint32_t path_id) {
19  Ip4Address addr(path_id);
20  return addr.to_string();
21 }
22 
23 BgpPath::BgpPath(const IPeer *peer, uint32_t path_id, PathSource src,
24  const BgpAttrPtr ptr, uint32_t flags, uint32_t label,
25  uint32_t l3_label)
26  : peer_(peer), path_id_(path_id), source_(src), attr_(ptr),
27  original_attr_(ptr), flags_(flags), label_(label), l3_label_(l3_label) {
28 }
29 
30 BgpPath::BgpPath(const IPeer *peer, PathSource src, const BgpAttrPtr ptr,
31  uint32_t flags, uint32_t label, uint32_t l3_label)
32  : peer_(peer), path_id_(0), source_(src), attr_(ptr), original_attr_(ptr),
33  flags_(flags), label_(label), l3_label_(l3_label) {
34 }
35 
36 BgpPath::BgpPath(uint32_t path_id, PathSource src, const BgpAttrPtr ptr,
37  uint32_t flags, uint32_t label, uint32_t l3_label)
38  : peer_(NULL), path_id_(path_id), source_(src), attr_(ptr),
39  original_attr_(ptr), flags_(flags), label_(label), l3_label_(l3_label) {
40 }
41 
43  uint32_t flags, uint32_t label, uint32_t l3_label)
44  : peer_(NULL), path_id_(0), source_(src), attr_(ptr), original_attr_(ptr),
45  flags_(flags), label_(label), l3_label_(l3_label) {
46 }
47 
48 // True is better
49 #define BOOL_COMPARE(CondA, CondB) \
50  do { \
51  if (CondA) { \
52  if (!(CondB)) return -1; \
53  } else { \
54  if (CondB) return 1; \
55  } \
56  } while (0)
57 
58 int BgpPath::PathCompare(const BgpPath &rhs, bool allow_ecmp) const {
59  const BgpAttr *rattr = rhs.GetAttr();
60 
61  // Feasible Path first
63 
64  // Compare local_pref in reverse order as larger is better.
65  KEY_COMPARE(rattr->local_pref(), attr_->local_pref());
66 
67  // ETree Root path first [compare in reverse order]
68  BOOL_COMPARE(rattr->etree_leaf(), attr_->etree_leaf());
69 
70  // Sticky paths first
71  BOOL_COMPARE(rattr->evpn_sticky_mac(), attr_->evpn_sticky_mac());
72 
73  // Compare sequence_number in reverse order as larger is better.
74  KEY_COMPARE(rattr->sequence_number(), attr_->sequence_number());
75 
76  // Route without LLGR_STALE community is always preferred over one with.
77  bool llgr_stale = attr_->community() && attr_->community()->ContainsValue(
79  llgr_stale |= IsLlgrStale();
80 
81  bool rllgr_stale = rattr->community() && rattr->community()->ContainsValue(
83  rllgr_stale |= rhs.IsLlgrStale();
84 
85  KEY_COMPARE(llgr_stale, rllgr_stale);
86 
87  // Do not compare as path length for service chain paths at this point.
88  // We want to treat service chain paths as ECMP irrespective of as path
89  // length.
90  const BgpServer *server = attr_->attr_db()->server();
91  if (!server->ignore_aspath() &&
92  (!attr_->origin_vn_path() || !rattr->origin_vn_path())) {
93  KEY_COMPARE(attr_->max_as_path_count(), rattr->max_as_path_count());
94  }
95 
96  KEY_COMPARE(attr_->origin(), rattr->origin());
97 
98  // Compare med if always compare med knob is enabled or if both paths are
99  // learnt from the same neighbor as.
100  if (server->global_config()->always_compare_med() ||
101  (attr_->neighbor_as() &&
102  attr_->neighbor_as() == rattr->neighbor_as())) {
103  KEY_COMPARE(attr_->med(), rattr->med());
104  }
105 
106  // For ECMP paths, above checks should suffice.
107  if (allow_ecmp)
108  return 0;
109 
110  // Prefer non-aliased paths.
111  BOOL_COMPARE(rhs.IsAliased(), IsAliased());
112 
113  // Compare as path length for service chain paths since we bypassed the
114  // check previously.
115  if (attr_->origin_vn_path() && rattr->origin_vn_path())
116  KEY_COMPARE(attr_->max_as_path_count(), rattr->max_as_path_count());
117 
118  // Prefer locally generated routes over bgp and xmpp routes.
119  BOOL_COMPARE(peer_ == NULL, rhs.peer_ == NULL);
120 
121  // Compare the source and the path id.
122  KEY_COMPARE(rhs.GetSource(), GetSource());
123 
124  // Bail if both paths are local since all subsequent checks are
125  // based on IPeer properties.
126  if (peer_ == NULL && rhs.peer_ == NULL) {
128  return 0;
129  }
130 
131  // Prefer xmpp routes over bgp routes.
133 
134  // Path received from EBGP is better than the one received from IBGP
136  rhs.peer_->PeerType() == BgpProto::IBGP);
137 
139 
140  // Lower router id is better. Substitute originator id for router id
141  // if the path has an originator id.
142  uint32_t orig_id = attr_->originator_id().to_ulong();
143  uint32_t rorig_id = rattr->originator_id().to_ulong();
144  uint32_t id = orig_id ? orig_id : peer_->bgp_identifier();
145  uint32_t rid = rorig_id ? rorig_id : rhs.peer_->bgp_identifier();
146  KEY_COMPARE(id, rid);
147 
148  KEY_COMPARE(attr_->cluster_list_length(), rattr->cluster_list_length());
149 
150  const BgpPeer *lpeer = dynamic_cast<const BgpPeer *>(peer_);
151  const BgpPeer *rpeer = dynamic_cast<const BgpPeer *>(rhs.peer_);
152  if (lpeer != NULL && rpeer != NULL) {
153  KEY_COMPARE(lpeer->peer_key(), rpeer->peer_key());
154  }
155 
156  return 0;
157 }
158 
159 bool BgpPath::PathSameNeighborAs(const BgpPath &rhs) const {
160  const BgpAttr *rattr = rhs.GetAttr();
161  if (!peer_ || peer_->PeerType() != BgpProto::EBGP)
162  return false;
163  if (!rhs.peer_ || rhs.peer_->PeerType() != BgpProto::EBGP)
164  return false;
165  return (attr_->neighbor_as() == rattr->neighbor_as());
166 }
167 
168 void BgpPath::UpdatePeerRefCount(int count, Address::Family family) const {
169  if (!peer_)
170  return;
171  peer_->UpdateTotalPathCount(count);
172  if (source_ != BGP_XMPP || IsReplicated() || IsResolved() || IsAliased())
173  return;
174  peer_->UpdatePrimaryPathCount(count, family);
175 }
176 
177 string BgpPath::ToString() const {
178  return peer_ ? peer_->ToString() : "Nil";
179 }
180 
182  if (!attr_->source_rd().IsZero())
183  return attr_->source_rd();
184  if (!IsReplicated())
186 
187  const BgpSecondaryPath *path = static_cast<const BgpSecondaryPath *>(this);
188  return path->GetPrimaryRouteDistinguisher();
189 }
190 
191 vector<string> BgpPath::GetFlagsStringList() const {
192  vector<string> flag_names;
193  if (flags_ == 0) {
194  flag_names.push_back("None");
195  return flag_names;
196  }
197 
198  // First we form a list of enums and then iterate over it to get their
199  // string forms using switch. This lets compiler tell us when ever we add a
200  // new enumeration to PathFlag.
201  vector<PathFlag> flags;
202  if (flags_ & AsPathLooped)
203  flags.push_back(AsPathLooped);
204  if (flags_ & NoNeighborAs)
205  flags.push_back(NoNeighborAs);
206  if (flags_ & Stale)
207  flags.push_back(Stale);
208  if (flags_ & NoTunnelEncap)
209  flags.push_back(NoTunnelEncap);
211  flags.push_back(OriginatorIdLooped);
212  if (flags_ & ResolveNexthop)
213  flags.push_back(ResolveNexthop);
214  if (flags_ & ResolvedPath)
215  flags.push_back(ResolvedPath);
217  flags.push_back(RoutingPolicyReject);
218  if (flags_ & LlgrStale)
219  flags.push_back(LlgrStale);
221  flags.push_back(ClusterListLooped);
222  if (flags_ & AliasedPath)
223  flags.push_back(AliasedPath);
225  flags.push_back(CheckGlobalErmVpnRoute);
226 
227  for (auto flag : flags) {
228  switch (flag) {
229  case AsPathLooped:
230  flag_names.push_back("AsPathLooped");
231  break;
232  case NoNeighborAs:
233  flag_names.push_back("NoNeighborAs");
234  break;
235  case Stale:
236  flag_names.push_back("Stale");
237  break;
238  case NoTunnelEncap:
239  flag_names.push_back("NoTunnelEncap");
240  break;
241  case OriginatorIdLooped:
242  flag_names.push_back("OriginatorIdLooped");
243  break;
244  case ResolveNexthop:
245  flag_names.push_back("ResolveNexthop");
246  break;
247  case ResolvedPath:
248  flag_names.push_back("ResolvedPath");
249  break;
250  case RoutingPolicyReject:
251  flag_names.push_back("RoutingPolicyReject");
252  break;
253  case LlgrStale:
254  flag_names.push_back("LlgrStale");
255  break;
256  case ClusterListLooped:
257  flag_names.push_back("ClusterListLooped");
258  break;
259  case AliasedPath:
260  flag_names.push_back("AliasedPath");
261  break;
262  case CheckGlobalErmVpnRoute:
263  flag_names.push_back("CheckGlobalErmVpnRoute");
264  break;
265  }
266  }
267  return flag_names;
268 }
269 
270 string BgpPath::GetSourceString(bool combine_bgp_and_xmpp) const {
271  switch (source_) {
272  case None:
273  return "None";
274  case BGP_XMPP:
275  if (combine_bgp_and_xmpp) {
276  return "BGP_XMPP";
277  } else if (peer_) {
278  return(peer_->IsXmppPeer() ? "XMPP" : "BGP");
279  } else {
280  return "None";
281  }
282  case ServiceChain:
283  return "ServiceChain";
284  case StaticRoute:
285  return "StaticRoute";
286  case Aggregate:
287  return "Aggregate";
288  case Local:
289  return "Local";
290  }
291  return "None";
292 }
293 
294 BgpSecondaryPath::BgpSecondaryPath(const IPeer *peer, uint32_t path_id,
295  PathSource src, const BgpAttrPtr ptr, uint32_t flags, uint32_t label,
296  uint32_t l3_label)
297  : BgpPath(peer, path_id, src, ptr, flags, label, l3_label) {
298 }
299 
302 }
303 
304 void BgpPath::AddExtCommunitySubCluster(uint32_t subcluster_id) {
305  BgpAttr *attr = new BgpAttr(*(GetOriginalAttr()));
306  BgpServer *server = attr->attr_db()->server();
307  ExtCommunityPtr ext_community = attr->ext_community();
308 
309  SubCluster sc(server->autonomous_system(), subcluster_id);
310  ext_community = server->extcomm_db()->
311  ReplaceSubClusterAndLocate(ext_community.get(),
312  sc.GetExtCommunity());
313  BgpAttrPtr modified_attr = server->attr_db()->
314  ReplaceExtCommunityAndLocate(attr, ext_community);
315  // Since routing policies are applied only to original attribute hence
316  // we are updating original_attr with subcluster extended community.
317  // Also we need to set modified_attr in attr as well as orignal_attr,
318  // because there may or may not be a policy but we still need to add this
319  // community.
320  // Modifying original attr should be done judiciously and only if required.
321  if (modified_attr) {
322  SetAttr(modified_attr, modified_attr);
323  }
324 }
const Community * community() const
Definition: bgp_attr.h:914
as_t neighbor_as() const
Definition: bgp_attr.cc:1132
uint32_t flags_
Definition: bgp_path.h:157
BgpPath(const IPeer *peer, uint32_t path_id, PathSource src, const BgpAttrPtr ptr, uint32_t flags, uint32_t label, uint32_t l3_label=0)
Definition: bgp_path.cc:23
uint32_t local_pref() const
Definition: bgp_attr.h:889
bool etree_leaf() const
Definition: bgp_attr.cc:1168
virtual void UpdatePrimaryPathCount(int count, Address::Family family=Address::UNSPEC) const =0
virtual bool IsXmppPeer() const =0
virtual uint32_t bgp_identifier() const =0
virtual BgpProto::BgpPeerType PeerType() const =0
static std::string PathIdString(uint32_t path_id)
Definition: bgp_path.cc:18
Family
Definition: address.h:24
#define KEY_COMPARE(x, y)
Definition: util.h:70
const uint32_t path_id_
Definition: bgp_path.h:150
BgpGlobalSystemConfig * global_config()
Definition: bgp_server.h:290
const OriginVnPath * origin_vn_path() const
Definition: bgp_attr.h:916
const Ip4Address & originator_id() const
Definition: bgp_attr.h:895
virtual std::string ToString() const
Definition: bgp_path.cc:177
Definition: ipeer.h:186
RouteDistinguisher GetPrimaryRouteDistinguisher() const
Definition: bgp_path.cc:300
BgpAttrDB * attr_db()
Definition: bgp_attr.h:928
std::string GetSourceString(bool combine_bgp_and_xmpp=false) const
Definition: bgp_path.cc:270
boost::intrusive_ptr< const BgpAttr > BgpAttrPtr
Definition: bgp_attr.h:991
bool always_compare_med() const
Definition: bgp_config.h:651
const BgpPeerKey & peer_key() const
Definition: bgp_peer.h:164
PathSource
Definition: bgp_path.h:37
BgpSecondaryPath(const IPeer *peer, uint32_t path_id, PathSource src, const BgpAttrPtr attr, uint32_t flags, uint32_t label, uint32_t l3_label=0)
Definition: bgp_path.cc:294
bool IsFeasible() const
Definition: bgp_path.h:92
PathSource GetSource() const
Definition: bgp_path.h:103
const IPeer * peer_
Definition: bgp_path.h:149
ExtCommunityDB * extcomm_db()
Definition: bgp_server.h:187
boost::intrusive_ptr< const ExtCommunity > ExtCommunityPtr
Definition: community.h:448
bool ContainsValue(uint32_t value) const
Definition: community.cc:113
virtual const std::string & ToString() const =0
size_t cluster_list_length() const
Definition: bgp_attr.h:908
void UpdatePeerRefCount(int count, Address::Family family) const
Definition: bgp_path.cc:168
static RouteDistinguisher kZeroRd
Definition: rd.h:14
BgpServer * server()
Definition: bgp_attr.h:1031
int PathCompare(const BgpPath &rhs, bool allow_ecmp) const
Definition: bgp_path.cc:58
bool IsResolved() const
Definition: bgp_path.h:99
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
virtual void UpdateTotalPathCount(int count) const =0
const BgpAttr * GetOriginalAttr() const
Definition: bgp_path.h:88
#define BOOL_COMPARE(CondA, CondB)
Definition: bgp_path.cc:49
const PathSource source_
Definition: bgp_path.h:151
const ExtCommunity * ext_community() const
Definition: bgp_attr.h:915
BgpAttrPtr attr_
Definition: bgp_path.h:154
BgpAttrDB * attr_db()
Definition: bgp_server.h:181
void AddExtCommunitySubCluster(uint32_t subcluster_id)
Definition: bgp_path.cc:304
bool IsLlgrStale() const
Definition: bgp_path.h:110
int max_as_path_count() const
Definition: bgp_attr.cc:1081
BgpAttrOrigin::OriginType origin() const
Definition: bgp_attr.h:881
const BgpRoute * src_entry_
Definition: bgp_path.h:192
const BgpAttr * GetAttr() const
Definition: bgp_path.h:87
std::vector< std::string > GetFlagsStringList() const
Definition: bgp_path.cc:191
bool IsAliased() const
Definition: bgp_path.h:98
uint32_t sequence_number() const
Definition: bgp_attr.cc:1140
uint32_t med() const
Definition: bgp_attr.h:888
bool ignore_aspath() const
Definition: bgp_server.h:307
RouteDistinguisher GetSourceRouteDistinguisher() const
Definition: bgp_path.cc:181
virtual bool IsReplicated() const
Definition: bgp_path.h:91
as_t autonomous_system() const
Definition: bgp_server.h:205
bool evpn_sticky_mac() const
Definition: bgp_attr.cc:1154
void SetAttr(const BgpAttrPtr attr, const BgpAttrPtr original_attr)
Definition: bgp_path.h:82
bool PathSameNeighborAs(const BgpPath &rhs) const
Definition: bgp_path.cc:159
virtual RouteDistinguisher GetRouteDistinguisher() const
Definition: bgp_route.h:56