OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
evpn_table.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "bgp/evpn/evpn_table.h"
6 
7 #include "bgp/ipeer.h"
8 #include "bgp/bgp_factory.h"
9 #include "bgp/bgp_evpn.h"
10 #include "bgp/bgp_server.h"
11 #include "bgp/bgp_update.h"
12 #include "bgp/inet/inet_table.h"
13 #include "bgp/inet6/inet6_table.h"
17 
18 using std::unique_ptr;
19 using std::string;
20 
21 size_t EvpnTable::HashFunction(const EvpnPrefix &prefix) {
22  if (prefix.type() == EvpnPrefix::MacAdvertisementRoute) {
23  if (prefix.mac_addr().IsBroadcast())
24  return 0;
25  const uint8_t *data = prefix.mac_addr().GetData();
26  uint32_t value = get_value(data + 2, 4);
27  return boost::hash_value(value);
28  }
29  if (prefix.type() == EvpnPrefix::IpPrefixRoute) {
30  if (prefix.ip_address().is_v4()) {
31  return InetTable::HashFunction(prefix.inet_prefix());
32  } else {
33  return Inet6Table::HashFunction(prefix.inet6_prefix());
34  }
35  }
36  return 0;
37 }
38 
39 EvpnTable::EvpnTable(DB *db, const string &name)
40  : BgpTable(db, name), evpn_manager_(NULL) {
41  mac_route_count_ = 0;
43  im_route_count_ = 0;
44  ip_route_count_ = 0;
45 }
46 
47 unique_ptr<DBEntry> EvpnTable::AllocEntry(
48  const DBRequestKey *key) const {
49  const RequestKey *pfxkey = static_cast<const RequestKey *>(key);
50  return unique_ptr<DBEntry> (new EvpnRoute(pfxkey->prefix));
51 }
52 
53 unique_ptr<DBEntry> EvpnTable::AllocEntryStr(
54  const string &key_str) const {
55  EvpnPrefix prefix = EvpnPrefix::FromString(key_str);
56  return unique_ptr<DBEntry> (new EvpnRoute(prefix));
57 }
58 
59 void EvpnTable::AddRemoveCallback(const DBEntryBase *entry, bool add) const {
60  if (IsVpnTable())
61  return;
62  const EvpnRoute *evpn_rt = static_cast<const EvpnRoute *>(entry);
63  const EvpnPrefix &evpn_prefix = evpn_rt->GetPrefix();
64  switch (evpn_prefix.type()) {
66  // Ignore Broadcast MAC routes.
67  if (evpn_prefix.mac_addr().IsBroadcast())
68  break;
69 
70  if (add) {
72  } else {
74  }
75 
76  // Ignore MAC routes with IP addresses.
77  if (evpn_prefix.family() != Address::UNSPEC)
78  break;
79 
80  if (add) {
82  } else {
84  }
85  break;
86 
88  if (add) {
90  } else {
92  }
93  break;
94 
96  if (add) {
98  } else {
100  }
101  break;
102 
103  default:
104  break;
105  }
106 }
107 
108 size_t EvpnTable::Hash(const DBRequestKey *key) const {
109  const RequestKey *rkey = static_cast<const RequestKey *>(key);
110  size_t value = HashFunction(rkey->prefix);
111  return value % DB::PartitionCount();
112 }
113 
114 size_t EvpnTable::Hash(const DBEntry *entry) const {
115  const EvpnRoute *rt_entry = static_cast<const EvpnRoute *>(entry);
116  size_t value = HashFunction(rt_entry->GetPrefix());
117  return value % DB::PartitionCount();
118 }
119 
121  const DBRequestKey *prefix) {
122  const RequestKey *pfxkey = static_cast<const RequestKey *>(prefix);
123  EvpnRoute rt_key(pfxkey->prefix);
124  return static_cast<BgpRoute *>(rtp->Find(&rt_key));
125 }
126 
128  if (routing_instance()->IsMasterRoutingInstance())
129  return NULL;
130  return (new PathResolver(this));
131 }
132 
133 DBTableBase *EvpnTable::CreateTable(DB *db, const string &name) {
134  EvpnTable *table = new EvpnTable(db, name);
135  table->Init();
136  return table;
137 }
138 
139 // Find the route.
141  EvpnRoute rt_key(prefix);
142  DBTablePartition *rtp = static_cast<DBTablePartition *>(
143  GetTablePartition(&rt_key));
144  return dynamic_cast<EvpnRoute *>(rtp->Find(&rt_key));
145 }
146 
147 const EvpnRoute *EvpnTable::FindRoute(const EvpnPrefix &prefix) const {
148  EvpnRoute rt_key(prefix);
149  const DBTablePartition *rtp = static_cast<const DBTablePartition *>(
150  GetTablePartition(&rt_key));
151  return dynamic_cast<const EvpnRoute *>(rtp->Find(&rt_key));
152 }
153 
155  const BgpTable *src_table,
156  const ExtCommunityPtr community,
157  const EvpnPrefix &evpn_prefix) const {
158  // Always replicate into master table.
159  if (IsMaster())
160  return true;
161 
162  // Always replicate Type-5 routes.
163  if (evpn_prefix.type() == EvpnPrefix::IpPrefixRoute)
164  return true;
165 
166  // Don't replicate to a VRF from other VRF tables.
167  const EvpnTable *src_evpn_table =
168  dynamic_cast<const EvpnTable *>(src_table);
169  if (!src_evpn_table->IsMaster())
170  return false;
171 
172  // Replicate to VRF from the VPN table if OriginVn matches.
173  if (community->ContainsOriginVn(server->autonomous_system(),
175  return true;
176  }
177 
178  // Do not replicate non AD routes as the OriginVN does not match.
179  if (evpn_prefix.type() != EvpnPrefix::AutoDiscoveryRoute)
180  return false;
181 
182  string es_target = server->autonomous_system() > 0xffFF ?
185 
186  // Replicate if AD route target is associated with the route.
187  RouteTarget rtarget = RouteTarget::FromString("target:" +
188  integerToString(server->autonomous_system()) + ":" + es_target);
189  if (community->ContainsRTarget(rtarget.GetExtCommunity()))
190  return true;
191  return false;
192 }
193 
195  BgpTable *src_table, BgpRoute *src_rt, const BgpPath *src_path,
196  ExtCommunityPtr community) {
197  assert(src_table->family() == Address::EVPN);
198  EvpnRoute *evpn_rt = dynamic_cast<EvpnRoute *>(src_rt);
199  assert(evpn_rt);
200  EvpnPrefix evpn_prefix(evpn_rt->GetPrefix());
201 
202  // Check if this evpn route should be replicated.
203  if (!ShouldReplicate(server, src_table, community, evpn_prefix))
204  return NULL;
205  if (evpn_prefix.type() == EvpnPrefix::AutoDiscoveryRoute) {
206  if (IsMaster() || evpn_prefix.tag() != EvpnPrefix::kMaxTag)
207  return NULL;
208  community = server->extcomm_db()->ReplaceRTargetAndLocate(
209  community.get(), ExtCommunity::ExtCommunityList());
210  }
211  if (evpn_prefix.type() == EvpnPrefix::SegmentRoute)
212  return NULL;
213  if (evpn_prefix.type() == EvpnPrefix::MacAdvertisementRoute &&
214  evpn_prefix.mac_addr().IsBroadcast())
215  return NULL;
216 
217  BgpAttrDB *attr_db = server->attr_db();
218  BgpAttrPtr new_attr(src_path->GetAttr());
219 
220  if (IsMaster()) {
221  if (evpn_prefix.route_distinguisher().IsZero()) {
222  if (new_attr->sub_protocol() == "bgpaas") {
223  boost::system::error_code ec;
224  Ip4Address addr =
225  Ip4Address::from_string(src_path->GetPeer()->ToString(), ec);
226  if ((ec.value() != 0)) {
227  evpn_prefix.set_route_distinguisher(new_attr->source_rd());
228  } else {
229  RouteDistinguisher new_source_rd =
230  RouteDistinguisher(addr.to_ulong(), 0);
231  evpn_prefix.set_route_distinguisher(new_source_rd);
232  }
233  } else {
234  evpn_prefix.set_route_distinguisher(new_attr->source_rd());
235  }
236  }
237  } else {
238  if (evpn_prefix.type() == EvpnPrefix::AutoDiscoveryRoute ||
239  evpn_prefix.type() == EvpnPrefix::MacAdvertisementRoute ||
240  evpn_prefix.type() == EvpnPrefix::IpPrefixRoute) {
241  evpn_prefix.set_route_distinguisher(RouteDistinguisher::kZeroRd);
242  }
243  }
244  EvpnRoute rt_key(evpn_prefix);
245 
246  // Find or create the route.
247  DBTablePartition *rtp =
248  static_cast<DBTablePartition *>(GetTablePartition(&rt_key));
249  BgpRoute *dest_route = static_cast<BgpRoute *>(rtp->Find(&rt_key));
250  if (dest_route == NULL) {
251  dest_route = new EvpnRoute(evpn_prefix);
252  rtp->Add(dest_route);
253  } else {
254  dest_route->ClearDelete();
255  }
256 
257  new_attr = attr_db->ReplaceExtCommunityAndLocate(new_attr.get(), community);
258 
259  // Check whether peer already has a path
260  BgpPath *dest_path = dest_route->FindSecondaryPath(src_rt,
261  src_path->GetSource(), src_path->GetPeer(),
262  src_path->GetPathId());
263  if (dest_path != NULL) {
264  if ((new_attr != dest_path->GetOriginalAttr()) ||
265  (src_path->GetFlags() != dest_path->GetFlags()) ||
266  (src_path->GetLabel() != dest_path->GetLabel()) ||
267  (src_path->GetL3Label() != dest_path->GetL3Label())) {
268  if (dest_path->NeedsResolution()) {
269  path_resolver()->StopPathResolution(rtp->index(), dest_path);
270  }
271  bool success = dest_route->RemoveSecondaryPath(src_rt,
272  src_path->GetSource(), src_path->GetPeer(),
273  src_path->GetPathId());
274  assert(success);
275  } else {
276  return dest_route;
277  }
278  }
279 
280  // Create replicated path and insert it on the route
281  BgpSecondaryPath *replicated_path =
282  new BgpSecondaryPath(src_path->GetPeer(), src_path->GetPathId(),
283  src_path->GetSource(), new_attr,
284  src_path->GetFlags(), src_path->GetLabel(),
285  src_path->GetL3Label());
286  replicated_path->SetReplicateInfo(src_table, src_rt);
287 
288  // For VPN to VRF replication, start path resolution if fast convergence is
289  // enabled and update path flag to indicate need for resolution.
290  if (!IsMaster() && server->IsNextHopCheckEnabled() &&
291  (replicated_path->GetSource() == BgpPath::BGP_XMPP)) {
292  Address::Family family = src_path->GetAttr()->nexthop_family();
293  RoutingInstanceMgr *mgr = server->routing_instance_mgr();
294  RoutingInstance *master_ri = mgr->GetDefaultRoutingInstance();
295  BgpTable *table = master_ri->GetTable(family);
296  replicated_path->SetResolveNextHop();
297  path_resolver()->StartPathResolution(dest_route,
298  replicated_path, table);
299  }
300 
301  dest_route->InsertPath(replicated_path);
302 
303  // Always trigger notification.
304  rtp->Notify(dest_route);
305 
306  return dest_route;
307 }
308 
309 bool EvpnTable::Export(RibOut *ribout, Route *route,
310  const RibPeerSet &peerset, UpdateInfoSList &uinfo_slist) {
311  EvpnRoute *evpn_route = dynamic_cast<EvpnRoute *>(route);
312  assert(evpn_route);
313 
314  if (ribout->IsEncodingBgp()) {
315  UpdateInfo *uinfo = GetUpdateInfo(ribout, evpn_route, peerset);
316  if (!uinfo)
317  return false;
318  uinfo_slist->push_front(*uinfo);
319  return true;
320  }
321 
322  const EvpnPrefix &evpn_prefix = evpn_route->GetPrefix();
323  if (evpn_prefix.type() != EvpnPrefix::MacAdvertisementRoute &&
324  evpn_prefix.type() != EvpnPrefix::IpPrefixRoute &&
325  evpn_prefix.type() != EvpnPrefix::SelectiveMulticastRoute) {
326  return false;
327  }
328 
329  if (!evpn_prefix.mac_addr().IsBroadcast() &&
330  (evpn_prefix.type() != EvpnPrefix::SelectiveMulticastRoute)) {
331  UpdateInfo *uinfo = GetUpdateInfo(ribout, evpn_route, peerset);
332  if (!uinfo)
333  return false;
334  uinfo_slist->push_front(*uinfo);
335  return true;
336  }
337 
339  return false;
340 
341  const IPeer *peer = evpn_route->BestPath()->GetPeer();
342  if (!peer || !ribout->IsRegistered(const_cast<IPeer *>(peer)))
343  return false;
344 
345  size_t peerbit = ribout->GetPeerIndex(const_cast<IPeer *>(peer));
346  if (!peerset.test(peerbit))
347  return false;
348 
349  UpdateInfo *uinfo = evpn_manager_->GetUpdateInfo(evpn_route);
350  if (!uinfo)
351  return false;
352 
353  uinfo->target.set(peerbit);
354  uinfo_slist->push_front(*uinfo);
355  return true;
356 }
357 
359  if (IsVpnTable())
360  return;
361  assert(!evpn_manager_);
362  evpn_manager_ = BgpStaticObjectFactory::Create<EvpnManager>(this);
364 }
365 
367  assert(evpn_manager_);
369  delete evpn_manager_;
370  evpn_manager_ = NULL;
371 }
372 
374  return evpn_manager_;
375 }
376 
378  return evpn_manager_;
379 }
380 
382  BgpTable::set_routing_instance(rtinstance);
384 }
385 
386 bool EvpnTable::IsMaster() const {
388 }
389 
390 static void RegisterFactory() {
392 }
393 
bool IsNextHopCheckEnabled() const
Definition: bgp_server.cc:697
virtual size_t Hash(const DBEntry *entry) const
Definition: evpn_table.cc:114
int GetPeerIndex(IPeerUpdate *peer) const
Definition: bgp_ribout.cc:537
LifetimeActor * deleter()
Return the LifetimeActor for the EvpnManager.
Definition: bgp_evpn.cc:1718
virtual Address::Family family() const
Definition: evpn_table.h:34
BgpTable * GetTable(Address::Family fmly)
const MacAddress & mac_addr() const
const BgpPath * BestPath() const
Definition: bgp_route.cc:46
static void RegisterFactory()
Definition: evpn_table.cc:390
bool test(size_t pos) const
Definition: bitset.cc:146
int virtual_network_index() const
UpdateInfo * GetUpdateInfo(RibOut *ribout, BgpRoute *route, const RibPeerSet &peerset)
Definition: bgp_table.cc:578
bool RemoveSecondaryPath(const BgpRoute *src_rt, BgpPath::PathSource src, const IPeer *peer, uint32_t path_id)
Definition: bgp_route.cc:397
#define EVPN_ES_IMPORT_ROUTE_TARGET_AS2
DBEntry * Find(const DBEntry *entry)
bool IsBroadcast() const
Definition: mac_address.cc:33
RoutingInstance * routing_instance()
Definition: bgp_table.h:148
Family
Definition: address.h:24
static size_t HashFunction(const EvpnPrefix &prefix)
Definition: evpn_table.cc:21
virtual bool Export(RibOut *ribout, Route *route, const RibPeerSet &peerset, UpdateInfoSList &info_slist)
Definition: evpn_table.cc:309
bool ShouldReplicate(const BgpServer *server, const BgpTable *src_table, const ExtCommunityPtr community, const EvpnPrefix &evpn_prefix) const
Definition: evpn_table.cc:154
Definition: route.h:14
void StartPathResolution(BgpRoute *route, const BgpPath *path, BgpTable *nh_table=NULL)
RoutingInstanceMgr * routing_instance_mgr()
Definition: bgp_server.h:102
const uint32_t GetPathId() const
Definition: bgp_path.h:78
EvpnManager * GetEvpnManager()
Definition: evpn_table.cc:373
RoutingInstance * GetDefaultRoutingInstance()
virtual Address::Family family() const =0
uint32_t GetFlags() const
Definition: bgp_path.h:100
static uint64_t get_value(const uint8_t *data, int size)
Definition: parse_object.h:39
Definition: ipeer.h:186
static DBTableBase * CreateTable(DB *db, const std::string &name)
Definition: evpn_table.cc:133
BgpAttrPtr ReplaceExtCommunityAndLocate(const BgpAttr *attr, ExtCommunityPtr extcomm)
Definition: bgp_attr.cc:1330
#define EVPN_ES_IMPORT_ROUTE_TARGET_AS4
const bytes_type & GetExtCommunity() const
uint32_t GetL3Label() const
Definition: bgp_path.h:90
Definition: db.h:24
tbb::atomic< uint64_t > unique_mac_route_count_
Definition: evpn_table.h:75
boost::intrusive_ptr< const BgpAttr > BgpAttrPtr
Definition: bgp_attr.h:991
void SetReplicateInfo(const BgpTable *table, const BgpRoute *rt)
Definition: bgp_path.h:172
virtual void Initialize()
Initialize the EvpnManager. We allocate the EvpnManagerPartitions and register a DBListener for the E...
Definition: bgp_evpn.cc:1058
tbb::atomic< uint64_t > im_route_count_
Definition: evpn_table.h:76
void Init()
Definition: db_table.cc:387
virtual bool IsVpnTable() const
Definition: evpn_table.h:36
PathSource GetSource() const
Definition: bgp_path.h:103
static const std::string integerToString(const NumberType &num)
Definition: string_util.h:19
Inet6Prefix inet6_prefix() const
RibPeerSet target
Definition: bgp_update.h:103
bool IsDeleted() const
Definition: lifetime.h:131
ExtCommunityDB * extcomm_db()
Definition: bgp_server.h:189
EvpnManager * evpn_manager_
Definition: evpn_table.h:73
boost::intrusive_ptr< const ExtCommunity > ExtCommunityPtr
Definition: community.h:448
static const uint32_t kMaxTag
This class represents the EVPN manager for an EvpnTable in a VRF.
Definition: bgp_evpn.h:578
virtual PathResolver * CreatePathResolver()
Definition: evpn_table.cc:127
Ip4Prefix inet_prefix() const
tbb::atomic< uint64_t > ip_route_count_
Definition: evpn_table.h:77
virtual std::unique_ptr< DBEntry > AllocEntry(const DBRequestKey *key) const
Definition: evpn_table.cc:47
bool IsRegistered(IPeerUpdate *peer)
Definition: bgp_ribout.cc:399
virtual const std::string & ToString() const =0
EvpnTable(DB *db, const std::string &name)
Definition: evpn_table.cc:39
uint8_t type() const
bool IsEncodingBgp() const
Definition: bgp_ribout.h:331
bool IsMaster() const
Definition: evpn_table.cc:386
IPeer * GetPeer()
Definition: bgp_path.h:76
static size_t HashFunction(const Ip4Prefix &addr)
Definition: inet_table.cc:28
static RouteDistinguisher kZeroRd
Definition: rd.h:14
virtual void Terminate()
Terminate the EvpnManager. We free the EvpnManagerPartitions and unregister from the EvpnTable...
Definition: bgp_evpn.cc:1075
void ClearDelete()
Definition: db_entry.h:48
static RouteTarget FromString(const std::string &str, boost::system::error_code *error=NULL)
uint32_t GetLabel() const
Definition: bgp_path.h:89
void SetResolveNextHop()
Definition: bgp_path.h:129
virtual BgpRoute * TableFind(DBTablePartition *rtp, const DBRequestKey *prefix)
Definition: evpn_table.cc:120
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
void InsertPath(BgpPath *path)
Definition: bgp_route.cc:60
const BgpAttr * GetOriginalAttr() const
Definition: bgp_path.h:88
virtual UpdateInfo * GetUpdateInfo(EvpnRoute *route)
Construct export state for the given EvpnRoute. Note that the route only needs to be exported to the ...
Definition: bgp_evpn.cc:1140
virtual DBTablePartBase * GetTablePartition(const DBRequestKey *key)
Definition: db_table.cc:436
const EvpnPrefix & GetPrefix() const
BitSet & set(size_t pos)
Definition: bitset.cc:125
static EvpnPrefix FromString(const std::string &str, boost::system::error_code *errorp=NULL)
Address::Family nexthop_family() const
Definition: bgp_attr.cc:1124
bool IsMasterRoutingInstance() const
BgpPath * FindSecondaryPath(BgpRoute *src_rt, BgpPath::PathSource src, const IPeer *peer, uint32_t path_id)
Definition: bgp_route.cc:372
void DestroyEvpnManager()
Definition: evpn_table.cc:366
virtual void AddRemoveCallback(const DBEntryBase *entry, bool add) const
Definition: evpn_table.cc:59
BgpAttrDB * attr_db()
Definition: bgp_server.h:183
std::vector< ExtCommunityValue > ExtCommunityList
Definition: community.h:153
virtual void set_routing_instance(RoutingInstance *rtinstance)
Definition: evpn_table.cc:381
void StopPathResolution(int part_id, const BgpPath *path)
const BgpAttr * GetAttr() const
Definition: bgp_path.h:87
EvpnRoute * FindRoute(const EvpnPrefix &prefix)
Definition: evpn_table.cc:140
tbb::atomic< uint64_t > mac_route_count_
Definition: evpn_table.h:74
virtual void set_routing_instance(RoutingInstance *rtinstance)
Definition: bgp_table.cc:81
IpAddress ip_address() const
const uint8_t * GetData() const
Definition: mac_address.h:143
static int PartitionCount()
Definition: db.cc:32
virtual void Add(DBEntry *entry)
static size_t HashFunction(const Inet6Prefix &addr)
Definition: inet6_table.cc:17
bool NeedsResolution() const
Definition: bgp_path.h:135
void Notify(DBEntryBase *entry)
std::size_t hash_value(BgpAttr const &attr)
Definition: bgp_attr.cc:1259
as_t autonomous_system() const
Definition: bgp_server.h:207
ExtCommunityPtr ReplaceRTargetAndLocate(const ExtCommunity *src, const ExtCommunity::ExtCommunityList &export_list)
Definition: community.cc:743
#define MODULE_INITIALIZER(Func)
Definition: util.h:61
void CreateEvpnManager()
Definition: evpn_table.cc:358
virtual BgpRoute * RouteReplicate(BgpServer *server, BgpTable *src_table, BgpRoute *src_rt, const BgpPath *path, ExtCommunityPtr ptr)
Definition: evpn_table.cc:194
virtual std::unique_ptr< DBEntry > AllocEntryStr(const std::string &key) const
Definition: evpn_table.cc:53
Address::Family family() const
PathResolver * path_resolver()
Definition: bgp_table.h:153
static void RegisterFactory(const std::string &prefix, CreateFunction create_fn)
Definition: db.cc:24
int index() const