OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ermvpn_table.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
6 
7 #include "bgp/ipeer.h"
8 #include "bgp/bgp_factory.h"
9 #include "bgp/bgp_multicast.h"
10 #include "bgp/bgp_mvpn.h"
11 #include "bgp/bgp_server.h"
12 #include "bgp/bgp_update.h"
13 #include "bgp/inet/inet_table.h"
16 
17 using std::unique_ptr;
18 using std::string;
19 
20 size_t ErmVpnTable::HashFunction(const ErmVpnPrefix &prefix) const {
21  return boost::hash_value(prefix.group().to_ulong());
22 }
23 
24 ErmVpnTable::ErmVpnTable(DB *db, const string &name)
25  : BgpTable(db, name), tree_manager_(NULL), mvpn_project_manager_(NULL) {
26 }
27 
28 unique_ptr<DBEntry> ErmVpnTable::AllocEntry(
29  const DBRequestKey *key) const {
30  const RequestKey *pfxkey = static_cast<const RequestKey *>(key);
31  return unique_ptr<DBEntry> (new ErmVpnRoute(pfxkey->prefix));
32 }
33 
34 
35 unique_ptr<DBEntry> ErmVpnTable::AllocEntryStr(
36  const string &key_str) const {
37  ErmVpnPrefix prefix = ErmVpnPrefix::FromString(key_str);
38  return unique_ptr<DBEntry> (new ErmVpnRoute(prefix));
39 }
40 
41 size_t ErmVpnTable::Hash(const DBEntry *entry) const {
42  const ErmVpnRoute *rt_entry = static_cast<const ErmVpnRoute *>(entry);
43  const ErmVpnPrefix &ermvpnprefix = rt_entry->GetPrefix();
44  size_t value = ErmVpnTable::HashFunction(ermvpnprefix);
45  return value % kPartitionCount;
46 }
47 
48 size_t ErmVpnTable::Hash(const Ip4Address &group) const {
49  return boost::hash_value(group.to_ulong()) % kPartitionCount;
50 }
51 
52 size_t ErmVpnTable::Hash(const DBRequestKey *key) const {
53  const RequestKey *rkey = static_cast<const RequestKey *>(key);
54  Ip4Prefix prefix(rkey->prefix.group(), 32);
55  size_t value = InetTable::HashFunction(prefix);
56  return value % kPartitionCount;
57 }
58 
60  const DBRequestKey *prefix) {
61  const RequestKey *pfxkey = static_cast<const RequestKey *>(prefix);
62  ErmVpnRoute rt_key(pfxkey->prefix);
63  return static_cast<BgpRoute *>(rtp->Find(&rt_key));
64 }
65 
66 DBTableBase *ErmVpnTable::CreateTable(DB *db, const string &name) {
67  ErmVpnTable *table = new ErmVpnTable(db, name);
68  table->Init();
69  return table;
70 }
71 
73  BgpTable *src_table, BgpRoute *src_rt, const BgpPath *src_path,
74  ExtCommunityPtr community) {
75  assert(src_table->family() == Address::ERMVPN);
76 
77  ErmVpnRoute *mroute = dynamic_cast<ErmVpnRoute *>(src_rt);
78  assert(mroute);
79 
80  // Native routes are not replicated to other VRFs or to the VPN table.
81  if (mroute->GetPrefix().type() == ErmVpnPrefix::NativeRoute)
82  return NULL;
83 
84  if (!IsMaster()) {
85  // Don't replicate to a VRF from other VRF tables.
86  ErmVpnTable *src_ermvpn_table = dynamic_cast<ErmVpnTable *>(src_table);
87  if (!src_ermvpn_table->IsMaster())
88  return NULL;
89 
90  // Don't replicate to VRF from the VPN table if OriginVn doesn't match.
91  if (!community->ContainsOriginVn(server->autonomous_system(),
93  return NULL;
94  }
95 
96  // RD is always zero in the VRF. When replicating to the VPN table, we
97  // pick up the RD from the SourceRD attribute. The SourceRD is always set
98  // for Local and Global routes that the multicast code adds to a VRF.
99  ErmVpnPrefix mprefix(mroute->GetPrefix());
100  if (IsMaster()) {
101  mprefix.set_route_distinguisher(src_path->GetAttr()->source_rd());
102  } else {
103  mprefix.set_route_distinguisher(RouteDistinguisher::kZeroRd);
104  }
105  ErmVpnRoute rt_key(mprefix);
106 
107  // Find or create the route.
108  DBTablePartition *rtp =
109  static_cast<DBTablePartition *>(GetTablePartition(&rt_key));
110  BgpRoute *dest_route = static_cast<BgpRoute *>(rtp->Find(&rt_key));
111  if (dest_route == NULL) {
112  dest_route = new ErmVpnRoute(mprefix);
113  rtp->Add(dest_route);
114  } else {
115  dest_route->ClearDelete();
116  }
117 
118  BgpAttrPtr new_attr =
119  server->attr_db()->ReplaceExtCommunityAndLocate(src_path->GetAttr(),
120  community);
121 
122  // Check whether peer already has a path.
123  BgpPath *dest_path = dest_route->FindSecondaryPath(src_rt,
124  src_path->GetSource(), src_path->GetPeer(),
125  src_path->GetPathId());
126  if (dest_path != NULL) {
127  if (new_attr != dest_path->GetOriginalAttr() ||
128  src_path->GetFlags() != dest_path->GetFlags()) {
129  bool success = dest_route->RemoveSecondaryPath(src_rt,
130  src_path->GetSource(), src_path->GetPeer(),
131  src_path->GetPathId());
132  assert(success);
133  } else {
134  return dest_route;
135  }
136  }
137 
138  // Create replicated path and insert it on the route.
139  BgpSecondaryPath *replicated_path =
140  new BgpSecondaryPath(src_path->GetPeer(), src_path->GetPathId(),
141  src_path->GetSource(), new_attr,
142  src_path->GetFlags(), src_path->GetLabel());
143  replicated_path->SetReplicateInfo(src_table, src_rt);
144  dest_route->InsertPath(replicated_path);
145  rtp->Notify(dest_route);
146 
147  return dest_route;
148 }
149 
150 bool ErmVpnTable::Export(RibOut *ribout, Route *route,
151  const RibPeerSet &peerset, UpdateInfoSList &uinfo_slist) {
152  if (ribout->IsEncodingBgp()) {
153  BgpRoute *bgp_route = static_cast<BgpRoute *> (route);
154  UpdateInfo *uinfo = GetUpdateInfo(ribout, bgp_route, peerset);
155  if (!uinfo)
156  return false;
157  uinfo_slist->push_front(*uinfo);
158  return true;
159  }
160 
161  ErmVpnRoute *ermvpn_route = dynamic_cast<ErmVpnRoute *>(route);
162  if (ermvpn_route->GetPrefix().type() != ErmVpnPrefix::NativeRoute &&
163  ermvpn_route->GetPrefix().type() != ErmVpnPrefix::GlobalTreeRoute)
164  return false;
165 
167  return false;
168 
169  const IPeer *peer = ermvpn_route->BestPath()->GetPeer();
170  if (!peer || !ribout->IsRegistered(const_cast<IPeer *>(peer)))
171  return false;
172 
173  size_t peerbit = ribout->GetPeerIndex(const_cast<IPeer *>(peer));
174  if (!peerset.test(peerbit))
175  return false;
176 
177  UpdateInfo *uinfo = tree_manager_->GetUpdateInfo(ermvpn_route);
178  if (!uinfo)
179  return false;
180 
181  uinfo->target.set(peerbit);
182  uinfo_slist->push_front(*uinfo);
183  return true;
184 }
185 
187  // Don't create the McastTreeManager for the VPN table.
188  if (IsMaster() && !server()->mvpn_ipv4_enable())
189  return;
190  assert(!tree_manager_);
191  tree_manager_ = BgpStaticObjectFactory::Create<McastTreeManager>(this);
193 }
194 
196  assert(tree_manager_);
198  delete tree_manager_;
199  tree_manager_ = NULL;
200 }
201 
203  return tree_manager_;
204 }
205 
207  return tree_manager_;
208 }
209 
211  BgpTable::set_routing_instance(rtinstance);
214 }
215 
217  // Don't create the MvpnProjectManager for the master table.
218  if (!server()->mvpn_ipv4_enable() || IsMaster())
219  return;
220  assert(!mvpn_project_manager_);
221  mvpn_project_manager_ = BgpStaticObjectFactory::Create<MvpnProjectManager>(this);
223 }
224 
226  assert(mvpn_project_manager_);
228  delete mvpn_project_manager_;
229  mvpn_project_manager_ = NULL;
230 }
231 
232 bool ErmVpnTable::IsMaster() const {
234 }
235 
236 // Find or create the route.
238  ErmVpnRoute rt_key(prefix);
239  DBTablePartition *rtp = static_cast<DBTablePartition *>(
240  GetTablePartition(&rt_key));
241  return static_cast<ErmVpnRoute *>(rtp->Find(&rt_key));
242 }
243 
244 const ErmVpnRoute *ErmVpnTable::FindRoute(const ErmVpnPrefix &prefix) const {
245  return const_cast<ErmVpnRoute *>(
246  static_cast<const ErmVpnTable *>(this)->FindRoute(prefix));
247 }
248 
250  Ip4Address *address) const {
252  mvpn_project_manager_->GetMvpnSourceAddress(ermvpn_rt, address);
253 }
254 
255 static void RegisterFactory() {
257 }
258 
virtual void set_routing_instance(RoutingInstance *rtinstance)
int GetPeerIndex(IPeerUpdate *peer) const
Definition: bgp_ribout.cc:536
size_t HashFunction(const ErmVpnPrefix &prefix) const
Definition: ermvpn_table.cc:20
const BgpPath * BestPath() const
Definition: bgp_route.cc:46
const ErmVpnPrefix & GetPrefix() const
Definition: ermvpn_route.h:81
bool test(size_t pos) const
Definition: bitset.cc:146
int virtual_network_index() const
McastTreeManager * tree_manager_
Definition: ermvpn_table.h:80
void CreateTreeManager()
ErmVpnTable(DB *db, const std::string &name)
Definition: ermvpn_table.cc:24
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
DBEntry * Find(const DBEntry *entry)
RoutingInstance * routing_instance()
Definition: bgp_table.h:148
MvpnProjectManager * mvpn_project_manager_
Definition: ermvpn_table.h:81
Definition: route.h:14
virtual void Initialize()
const uint32_t GetPathId() const
Definition: bgp_path.h:78
static void RegisterFactory()
static DBTableBase * CreateTable(DB *db, const std::string &name)
Definition: ermvpn_table.cc:66
virtual BgpRoute * RouteReplicate(BgpServer *server, BgpTable *src_table, BgpRoute *src_rt, const BgpPath *path, ExtCommunityPtr ptr)
Definition: ermvpn_table.cc:72
const RouteDistinguisher & source_rd() const
Definition: bgp_attr.h:896
virtual Address::Family family() const =0
uint32_t GetFlags() const
Definition: bgp_path.h:100
Definition: ipeer.h:186
const ErmVpnRoute * FindRoute(const ErmVpnPrefix &prefix) const
void CreateMvpnProjectManager()
virtual void Initialize()
Definition: bgp_mvpn.cc:116
static ErmVpnPrefix FromString(const std::string &str, boost::system::error_code *errorp=NULL)
BgpAttrPtr ReplaceExtCommunityAndLocate(const BgpAttr *attr, ExtCommunityPtr extcomm)
Definition: bgp_attr.cc:1330
void GetMvpnSourceAddress(ErmVpnRoute *ermvpn_route, Ip4Address *address) const
Definition: bgp_mvpn.cc:1209
virtual UpdateInfo * GetUpdateInfo(ErmVpnRoute *route)
virtual bool Export(RibOut *ribout, Route *route, const RibPeerSet &peerset, UpdateInfoSList &info_slist)
Definition: db.h:24
boost::intrusive_ptr< const BgpAttr > BgpAttrPtr
Definition: bgp_attr.h:991
void SetReplicateInfo(const BgpTable *table, const BgpRoute *rt)
Definition: bgp_path.h:172
uint8_t type() const
Definition: ermvpn_route.h:56
void Init()
Definition: db_table.cc:387
PathSource GetSource() const
Definition: bgp_path.h:103
McastTreeManager * GetTreeManager()
RibPeerSet target
Definition: bgp_update.h:103
bool IsDeleted() const
Definition: lifetime.h:131
boost::intrusive_ptr< const ExtCommunity > ExtCommunityPtr
Definition: community.h:448
bool IsRegistered(IPeerUpdate *peer)
Definition: bgp_ribout.cc:398
virtual size_t Hash(const DBEntry *entry) const
Definition: ermvpn_table.cc:41
virtual void Terminate()
bool IsEncodingBgp() const
Definition: bgp_ribout.h:331
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
bool IsMaster() const
void ClearDelete()
Definition: db_entry.h:48
uint32_t GetLabel() const
Definition: bgp_path.h:89
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
static const int kPartitionCount
Definition: ermvpn_table.h:21
void InsertPath(BgpPath *path)
Definition: bgp_route.cc:60
Ip4Address group() const
Definition: ermvpn_route.h:59
const BgpAttr * GetOriginalAttr() const
Definition: bgp_path.h:88
virtual DBTablePartBase * GetTablePartition(const DBRequestKey *key)
Definition: db_table.cc:436
void DestroyTreeManager()
BgpServer * server()
Definition: bgp_table.cc:88
BitSet & set(size_t pos)
Definition: bitset.cc:125
bool IsMasterRoutingInstance() const
BgpPath * FindSecondaryPath(BgpRoute *src_rt, BgpPath::PathSource src, const IPeer *peer, uint32_t path_id)
Definition: bgp_route.cc:372
void DestroyMvpnProjectManager()
BgpAttrDB * attr_db()
Definition: bgp_server.h:181
void set_route_distinguisher(const RouteDistinguisher &rd)
Definition: ermvpn_route.h:61
virtual BgpRoute * TableFind(DBTablePartition *rtp, const DBRequestKey *prefix)
Definition: ermvpn_table.cc:59
virtual void Terminate()
Definition: bgp_mvpn.cc:128
const BgpAttr * GetAttr() const
Definition: bgp_path.h:87
virtual void set_routing_instance(RoutingInstance *rtinstance)
Definition: bgp_table.cc:81
void GetMvpnSourceAddress(ErmVpnRoute *ermvpn_route, Ip4Address *address) const
virtual void Add(DBEntry *entry)
void Notify(DBEntryBase *entry)
std::size_t hash_value(BgpAttr const &attr)
Definition: bgp_attr.cc:1259
LifetimeActor * deleter()
virtual std::unique_ptr< DBEntry > AllocEntryStr(const std::string &key) const
Definition: ermvpn_table.cc:35
as_t autonomous_system() const
Definition: bgp_server.h:205
virtual std::unique_ptr< DBEntry > AllocEntry(const DBRequestKey *key) const
Definition: ermvpn_table.cc:28
#define MODULE_INITIALIZER(Func)
Definition: util.h:61
static void RegisterFactory(const std::string &prefix, CreateFunction create_fn)
Definition: db.cc:24