OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
inet_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/inet/inet_table.h"
6 
7 #include <boost/foreach.hpp>
8 
10 #include "bgp/bgp_server.h"
11 #include "bgp/bgp_update.h"
18 
19 using std::unique_ptr;
20 using std::string;
21 
22 InetTable::InetTable(DB *db, const string &name)
23  : BgpTable(db, name) {
24  family_ = (name.at(name.length()-1) == '3') ?
26 }
27 
28 size_t InetTable::HashFunction(const Ip4Prefix &prefix) {
29  return boost::hash_value(prefix.ip4_addr().to_ulong());
30 }
31 
32 unique_ptr<DBEntry> InetTable::AllocEntry(const DBRequestKey *key) const {
33  const RequestKey *pfxkey = static_cast<const RequestKey *>(key);
34  return unique_ptr<DBEntry>(new InetRoute(pfxkey->prefix));
35 }
36 
37 unique_ptr<DBEntry> InetTable::AllocEntryStr(const string &key_str) const {
38  Ip4Prefix prefix = Ip4Prefix::FromString(key_str);
39  return unique_ptr<DBEntry>(new InetRoute(prefix));
40 }
41 
42 size_t InetTable::Hash(const DBEntry *entry) const {
43  const InetRoute *rt_entry = static_cast<const InetRoute *>(entry);
44  size_t value = HashFunction(rt_entry->GetPrefix());
45  return value % DB::PartitionCount();
46 }
47 
48 size_t InetTable::Hash(const DBRequestKey *key) const {
49  const RequestKey *rkey = static_cast<const RequestKey *>(key);
50  size_t value = HashFunction(rkey->prefix);
51  return value % DB::PartitionCount();
52 }
53 
55  const DBRequestKey *prefix) {
56  const RequestKey *pfxkey = static_cast<const RequestKey *>(prefix);
57  InetRoute rt_key(pfxkey->prefix);
58  return static_cast<BgpRoute *>(rtp->Find(&rt_key));
59 }
60 
61 DBTableBase *InetTable::CreateTable(DB *db, const string &name) {
62  InetTable *table = new InetTable(db, name);
63  table->Init();
64  return table;
65 }
66 
68  BgpTable *src_table, BgpRoute *src_rt, const BgpPath *path,
69  ExtCommunityPtr community) {
70  InetRoute *inet= dynamic_cast<InetRoute *> (src_rt);
71 
72  boost::scoped_ptr<Ip4Prefix> inet_prefix;
74 
75  if (inet) {
76  inet_prefix.reset(new Ip4Prefix(inet->GetPrefix().ip4_addr(),
77  inet->GetPrefix().prefixlen()));
78  } else {
79  InetVpnRoute *inetvpn = dynamic_cast<InetVpnRoute *> (src_rt);
80  assert(inetvpn);
81  rd = inetvpn->GetPrefix().route_distinguisher();
82  inet_prefix.reset(new Ip4Prefix(inetvpn->GetPrefix().addr(),
83  inetvpn->GetPrefix().prefixlen()));
84  }
85 
86  InetRoute rt_key(*inet_prefix);
87  DBTablePartition *rtp =
88  static_cast<DBTablePartition *>(GetTablePartition(&rt_key));
89  BgpRoute *dest_route = static_cast<BgpRoute *>(rtp->Find(&rt_key));
90  if (dest_route == NULL) {
91  dest_route = new InetRoute(rt_key.GetPrefix());
92  rtp->Add(dest_route);
93  } else {
94  dest_route->ClearDelete();
95  }
96 
97  BgpAttrDB *attr_db = server->attr_db();
98  BgpAttrPtr new_attr = attr_db->ReplaceExtCommunityAndLocate(path->GetAttr(),
99  community);
100 
101  // Set the RD attr if route is replicated from vpn table
102  if (!inet) {
103  new_attr = attr_db->ReplaceSourceRdAndLocate(new_attr.get(), rd);
104  }
105 
106  // Check whether there's already a path with the given peer and path id.
107  BgpPath *dest_path = dest_route->FindSecondaryPath(src_rt,
108  path->GetSource(), path->GetPeer(),
109  path->GetPathId());
110  uint32_t prev_flags = 0 , prev_label = 0;
111  const BgpAttr *prev_attr = NULL;
112  if (dest_path != NULL) {
113  prev_flags = dest_path->GetFlags();
114  prev_label = dest_path->GetLabel();
115  prev_attr = dest_path->GetOriginalAttr();
116  if ((new_attr != prev_attr) ||
117  (path->GetFlags() != prev_flags) ||
118  (path->GetLabel() != prev_label)) {
119  // Update Attributes and notify (if needed)
120  if (dest_path->NeedsResolution()) {
121  path_resolver()->StopPathResolution(rtp->index(), dest_path);
122  }
123  assert(dest_route->RemoveSecondaryPath(src_rt, path->GetSource(),
124  path->GetPeer(), path->GetPathId()));
125  } else {
126  return dest_route;
127  }
128  }
129 
130  BgpSecondaryPath *replicated_path =
131  new BgpSecondaryPath(path->GetPeer(), path->GetPathId(),
132  path->GetSource(), new_attr, path->GetFlags(), path->GetLabel());
133  replicated_path->SetReplicateInfo(src_table, src_rt);
134 
135  // For VPN to VRF replication, start path resolution if fast convergence is
136  // enabled and update path flag to indicate need for resolution.
137  if (!inet && (server->IsNextHopCheckEnabled()) &&
138  (replicated_path->GetSource() == BgpPath::BGP_XMPP)) {
139  Address::Family family = replicated_path->GetAttr()->nexthop_family();
140  RoutingInstanceMgr *mgr = server->routing_instance_mgr();
141  RoutingInstance *master_ri = mgr->GetDefaultRoutingInstance();
142  BgpTable *table = master_ri->GetTable(family);
143  replicated_path->SetResolveNextHop();
144  path_resolver()->StartPathResolution(dest_route, replicated_path,
145  table);
146  }
147 
148  dest_route->InsertPath(replicated_path);
149 
150  // BgpRoute::InsertPath() triggers routing policies processing, which may
151  // change the flags (namely, RoutingPolicyReject). So we check the flags
152  // once again and only notify the partition if the new path is still
153  // different after routing policies were applied.
154  bool notify = true;
155  if (dest_path != NULL) {
156  if ((replicated_path->GetOriginalAttr() == prev_attr) &&
157  (replicated_path->GetFlags() == prev_flags) &&
158  (replicated_path->GetLabel() == prev_label))
159  notify = false;
160  }
161 
162  // Notify the route even if the best path may not have changed. For XMPP
163  // peers, we support sending multiple ECMP next-hops for a single route.
164  //
165  // TODO(ananth): Can be optimized for changes that does not result in
166  // any change to ECMP list.
167  if (notify)
168  rtp->Notify(dest_route);
169 
170  return dest_route;
171 }
172 
173 bool InetTable::Export(RibOut *ribout, Route *route, const RibPeerSet &peerset,
174  UpdateInfoSList &uinfo_slist) {
175  BgpRoute *bgp_route = static_cast<BgpRoute *>(route);
176 
177  UpdateInfo *uinfo = GetUpdateInfo(ribout, bgp_route, peerset);
178  if (!uinfo)
179  return false;
180 
181  if (ribout->ExportPolicy().encoding == RibExportPolicy::BGP) {
182  BgpAttrDB *attr_db = routing_instance()->server()->attr_db();
184 
185  // Strip OriginVnPath.
186  if (uinfo->roattr.attr()->origin_vn_path()) {
187  BgpAttrPtr new_attr = attr_db->ReplaceOriginVnPathAndLocate(
188  uinfo->roattr.attr(), NULL);
189  uinfo->roattr.set_attr(this, new_attr);
190  }
191  }
192  uinfo_slist->push_front(*uinfo);
193 
194  return true;
195 }
196 
197 // Strip all extended-communities except OriginVN.
199  ExtCommunityPtr ext_commp = roattr->attr()->ext_community();
200  if (!ext_commp)
201  return;
202 
203  // Retrieve any origin_vn already present.
204  ExtCommunity::ExtCommunityValue const *origin_vnp = NULL;
205  BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &comm,
206  ext_commp->communities()) {
207  if (!ExtCommunity::is_origin_vn(comm))
208  continue;
209  origin_vnp = &comm;
210  break;
211  }
212 
213  BgpAttrDB *attr_db = routing_instance()->server()->attr_db();
214 
215  // If there is no origin-vn, then remove all other extended communities.
216  if (!origin_vnp) {
217  BgpAttrPtr new_attr = attr_db->ReplaceExtCommunityAndLocate(
218  roattr->attr(), NULL);
219  roattr->set_attr(this, new_attr);
220  return;
221  }
222 
223  // Remove all communities other than OriginVN by replacing all of the
224  // extended-community with just OriginVN.
225  if (ext_commp->communities().size() > 1) {
227  list.push_back(*origin_vnp);
228  ExtCommunityDB *extcomm_db =
230  ext_commp = extcomm_db->AppendAndLocate(NULL, list);
231  BgpAttrPtr new_attr = attr_db->ReplaceExtCommunityAndLocate(
232  roattr->attr(), ext_commp);
233  roattr->set_attr(this, new_attr);
234  }
235 }
236 
237 // Attach OriginVN extended-community from inetvpn path attribute if present
238 // into inet route path attribute.
240  const BgpAttrPtr inet_attrp) {
242 
243  // Check if origin-vn path attribute in inet.0 table path is identical to
244  // what is in inetvpn table path.
245  ExtCommunity::ExtCommunityValue const *inetvpn_rt_origin_vn = NULL;
246  if (inetvpn_attrp && inetvpn_attrp->ext_community()) {
247  BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &comm,
248  inetvpn_attrp->ext_community()->communities()) {
249  if (!ExtCommunity::is_origin_vn(comm))
250  continue;
251  inetvpn_rt_origin_vn = &comm;
252  break;
253  }
254  }
255 
256  ExtCommunity::ExtCommunityValue const *inet_rt_origin_vn = NULL;
257  if (inet_attrp && inet_attrp->ext_community()) {
258  BOOST_FOREACH(const ExtCommunity::ExtCommunityValue &comm,
259  inet_attrp->ext_community()->communities()) {
260  if (!ExtCommunity::is_origin_vn(comm))
261  continue;
262  inet_rt_origin_vn = &comm;
263  break;
264  }
265  }
266 
267  // Ignore if there is no change.
268  if (inetvpn_rt_origin_vn == inet_rt_origin_vn)
269  return inet_attrp;
270 
271  // Update/Delete inet route attributes with updated OriginVn community.
272  ExtCommunityPtr new_ext_community;
273  if (!inetvpn_rt_origin_vn) {
274  new_ext_community = server->extcomm_db()->RemoveOriginVnAndLocate(
275  inet_attrp->ext_community());
276  } else {
277  new_ext_community = server->extcomm_db()->ReplaceOriginVnAndLocate(
278  inet_attrp->ext_community(), *inetvpn_rt_origin_vn);
279  }
280 
281  return server->attr_db()->ReplaceExtCommunityAndLocate(inet_attrp.get(),
282  new_ext_community);
283 }
284 
286  BgpAttrPtr inet_attrp, const IPeer *peer) {
287  CHECK_CONCURRENCY("db::DBTable");
288 
289  BgpAttrPtr attrp = GetFabricAttributes(rt, inet_attrp, peer);
290  return GetMvpnAttributes(attrp);
291 }
292 
295  if (server->mvpn_ipv4_enable()) {
296  VrfRouteImport vit(server->bgp_identifier(),
297  routing_instance()->index());
298  ExtCommunityPtr ext =
300  attrp->ext_community(), vit.GetExtCommunity());
301  SourceAs sas(server->autonomous_system(), 0);
302  ext = server->extcomm_db()->ReplaceSourceASAndLocate(ext.get(),
303  sas.GetExtCommunity());
304  BgpAttrPtr new_attr =
305  server->attr_db()->ReplaceExtCommunityAndLocate(attrp.get(), ext);
306  return new_attr;
307  }
308  return attrp;
309 }
310 
311 // Given an inet prefix, update OriginVN with corresponding inetvpn route's
312 // path attribute.
314  BgpAttrPtr inet_attrp, const IPeer *peer) {
315 
316  if (!routing_instance()->IsMasterRoutingInstance())
317  return inet_attrp;
318  if (!inet_attrp || inet_attrp->source_rd().IsZero())
319  return inet_attrp;
320 
321  const InetRoute *inet_rt = dynamic_cast<InetRoute *>(rt);
322  const Ip4Prefix inet_prefix = inet_rt->GetPrefix();
323  RequestKey inet_rt_key(inet_prefix, NULL);
324  DBTablePartition *inet_partition = dynamic_cast<DBTablePartition *>(
325  GetTablePartition(&inet_rt_key));
326 
327  InetVpnTable *inetvpn_table = dynamic_cast<InetVpnTable *>(
329  assert(inetvpn_table);
330  InetVpnPrefix inetvpn_prefix(inet_attrp->source_rd(),
331  inet_prefix.ip4_addr(),
332  inet_prefix.prefixlen());
333  InetVpnTable::RequestKey inetvpn_rt_key(inetvpn_prefix, NULL);
334  DBTablePartition *inetvpn_partition = dynamic_cast<DBTablePartition *>(
335  inetvpn_table->GetTablePartition(&inetvpn_rt_key));
336 
337  // Assert that the partition indicies are identical. This is a MUST
338  // requirement as we need to peek into tables across different families.
339  assert(inet_partition->index() == inetvpn_partition->index());
340  InetVpnRoute *inetvpn_route = dynamic_cast<InetVpnRoute *>(
341  inetvpn_table->TableFind(inetvpn_partition, &inetvpn_rt_key));
342  if (!inetvpn_route)
343  return inet_attrp;
344  BgpPath *inetvpn_path = inetvpn_route->FindPath(peer, true);
345  if (!inetvpn_path)
346  return inet_attrp;
347  return UpdateAttributes(inetvpn_path->GetAttr(), inet_attrp);
348 }
349 
350 // Update inet route path attributes with OriginVN from corresponding inetvpn
351 // route path attribute.
352 void InetTable::UpdateRoute(const InetVpnPrefix &inetvpn_prefix,
353  const IPeer *peer, BgpAttrPtr inetvpn_attrp) {
354  CHECK_CONCURRENCY("db::DBTable");
355  assert(routing_instance()->IsMasterRoutingInstance());
356 
357  // Check if a route is present in inet.0 table for this prefix.
358  Ip4Prefix inet_prefix(inetvpn_prefix.addr(), inetvpn_prefix.prefixlen());
359  InetTable::RequestKey inet_rt_key(inet_prefix, NULL);
360  DBTablePartition *inet_partition = dynamic_cast<DBTablePartition *>(
361  GetTablePartition(&inet_rt_key));
362 
363  InetVpnTable *inetvpn_table = dynamic_cast<InetVpnTable *>(
365  assert(inetvpn_table);
366  InetVpnTable::RequestKey inetvpn_rt_key(inetvpn_prefix, NULL);
367  DBTablePartition *inetvpn_partition =
368  static_cast<DBTablePartition *>(inetvpn_table->GetTablePartition(
369  &inetvpn_rt_key));
370  assert(inet_partition->index() == inetvpn_partition->index());
371 
372  InetRoute *inet_route = dynamic_cast<InetRoute *>(
373  TableFind(inet_partition, &inet_rt_key));
374  if (!inet_route)
375  return;
376 
377  BgpPath *inet_path = inet_route->FindPath(peer);
378  if (!inet_path)
379  return;
380  BgpAttrPtr inet_attrp = inet_path->GetAttr();
381  if (!inet_attrp)
382  return;
383 
384  // Bail if the RDs do not match.
385  if (!(inet_attrp->source_rd() == inetvpn_prefix.route_distinguisher())) {
386  return;
387  }
388  BgpAttrPtr new_inet_attrp = UpdateAttributes(inetvpn_attrp, inet_attrp);
389  if (new_inet_attrp == inet_attrp)
390  return;
391 
392  // Update route with OriginVN path attribute.
393  inet_path->SetAttr(new_inet_attrp, inet_path->GetOriginalAttr());
394  inet_route->Notify();
395 }
396 
398  if (routing_instance()->IsMasterRoutingInstance())
399  return NULL;
400  return (new PathResolver(this));
401 }
402 
403 static void RegisterFactory() {
406 }
407 
bool IsNextHopCheckEnabled() const
Definition: bgp_server.cc:690
ExtCommunityPtr AppendAndLocate(const ExtCommunity *src, const ExtCommunity::ExtCommunityList &list)
Definition: community.cc:696
ExtCommunityPtr ReplaceOriginVnAndLocate(const ExtCommunity *src, const ExtCommunity::ExtCommunityValue &origin_vn)
Definition: community.cc:884
boost::array< uint8_t, 8 > ExtCommunityValue
Definition: community.h:152
BgpTable * GetTable(Address::Family fmly)
RibOutAttr roattr
Definition: bgp_update.h:100
const BgpAttr * attr() const
Definition: bgp_ribout.h:97
static void RegisterFactory()
Definition: inet_table.cc:403
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
BgpServer * server()
DBEntry * Find(const DBEntry *entry)
BgpAttrPtr UpdateAttributes(const BgpAttrPtr inetvpn_attrp, const BgpAttrPtr inet_attrp)
Definition: inet_table.cc:239
RoutingInstance * routing_instance()
Definition: bgp_table.h:148
Family
Definition: address.h:24
Ip4Address addr() const
const RibExportPolicy & ExportPolicy() const
Definition: bgp_ribout.h:308
ExtCommunityPtr RemoveOriginVnAndLocate(const ExtCommunity *src)
Definition: community.cc:871
Definition: route.h:14
void UpdateRoute(const InetVpnPrefix &inetvpn_prefix, const IPeer *peer, BgpAttrPtr inetvpn_attrp)
Definition: inet_table.cc:352
virtual std::unique_ptr< DBEntry > AllocEntry(const DBRequestKey *key) const
Definition: inet_table.cc:32
const InetVpnPrefix & GetPrefix() const
Definition: inetvpn_route.h:27
void StartPathResolution(BgpRoute *route, const BgpPath *path, BgpTable *nh_table=NULL)
virtual size_t Hash(const DBEntry *entry) const
Definition: inet_table.cc:42
RoutingInstanceMgr * routing_instance_mgr()
Definition: bgp_server.h:102
const uint32_t GetPathId() const
Definition: bgp_path.h:78
const OriginVnPath * origin_vn_path() const
Definition: bgp_attr.h:916
const RouteDistinguisher & route_distinguisher() const
RoutingInstance * GetDefaultRoutingInstance()
virtual BgpRoute * TableFind(DBTablePartition *rtp, const DBRequestKey *prefix)
virtual PathResolver * CreatePathResolver()
Definition: inet_table.cc:397
static DBTableBase * CreateTable(DB *db, const std::string &name)
Definition: inet_table.cc:61
uint32_t GetFlags() const
Definition: bgp_path.h:100
Definition: ipeer.h:186
int prefixlen() const
Definition: inet_route.h:27
BgpAttrPtr ReplaceExtCommunityAndLocate(const BgpAttr *attr, ExtCommunityPtr extcomm)
Definition: bgp_attr.cc:1330
virtual Address::Family family() const
Definition: inet_table.h:37
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
Ip4Address ip4_addr() const
Definition: inet_route.h:25
void Init()
Definition: db_table.cc:387
BgpRoute * RouteReplicate(BgpServer *server, BgpTable *src_tbl, BgpRoute *src_rt, const BgpPath *path, ExtCommunityPtr ptr)
Definition: inet_table.cc:67
PathSource GetSource() const
Definition: bgp_path.h:103
ExtCommunityDB * extcomm_db()
Definition: bgp_server.h:187
boost::intrusive_ptr< const ExtCommunity > ExtCommunityPtr
Definition: community.h:448
bool mvpn_ipv4_enable() const
Definition: bgp_server.h:303
static Ip4Prefix FromString(const std::string &str, boost::system::error_code *errorp=NULL)
Definition: inet_route.cc:84
void set_attr(const BgpTable *table, const BgpAttrPtr &attrp)
Definition: bgp_ribout.h:98
#define CHECK_CONCURRENCY(...)
virtual BgpAttrPtr GetAttributes(BgpRoute *rt, BgpAttrPtr attrp, const IPeer *peer)
Definition: inet_table.cc:285
IPeer * GetPeer()
Definition: bgp_path.h:76
BgpAttrPtr ReplaceSourceRdAndLocate(const BgpAttr *attr, const RouteDistinguisher &source_rd)
Definition: bgp_attr.cc:1362
static size_t HashFunction(const Ip4Prefix &addr)
Definition: inet_table.cc:28
void ClearDelete()
Definition: db_entry.h:48
void UpdateExtendedCommunity(RibOutAttr *roattr)
Definition: inet_table.cc:198
uint32_t GetLabel() const
Definition: bgp_path.h:89
void SetResolveNextHop()
Definition: bgp_path.h:129
const Ip4Prefix & GetPrefix() const
Definition: inet_route.h:70
BgpAttrPtr GetMvpnAttributes(BgpAttrPtr attrp)
Definition: inet_table.cc:293
ExtCommunityPtr ReplaceSourceASAndLocate(const ExtCommunity *src, const ExtCommunity::ExtCommunityValue &sas)
Definition: community.cc:828
void InsertPath(BgpPath *path)
Definition: bgp_route.cc:60
const BgpAttr * GetOriginalAttr() const
Definition: bgp_path.h:88
virtual DBTablePartBase * GetTablePartition(const DBRequestKey *key)
Definition: db_table.cc:436
BgpServer * server()
Definition: bgp_table.cc:88
uint32_t bgp_identifier() const
Definition: bgp_server.h:208
Address::Family nexthop_family() const
Definition: bgp_attr.cc:1124
BgpPath * FindSecondaryPath(BgpRoute *src_rt, BgpPath::PathSource src, const IPeer *peer, uint32_t path_id)
Definition: bgp_route.cc:372
const ExtCommunity * ext_community() const
Definition: bgp_attr.h:915
Address::Family family_
Definition: inet_table.h:71
BgpAttrDB * attr_db()
Definition: bgp_server.h:181
std::vector< ExtCommunityValue > ExtCommunityList
Definition: community.h:153
void StopPathResolution(int part_id, const BgpPath *path)
const BgpAttr * GetAttr() const
Definition: bgp_path.h:87
virtual bool Export(RibOut *ribout, Route *route, const RibPeerSet &peerset, UpdateInfoSList &info_slist)
Definition: inet_table.cc:173
static int PartitionCount()
Definition: db.cc:32
virtual void Add(DBEntry *entry)
bool NeedsResolution() const
Definition: bgp_path.h:135
int prefixlen() const
void Notify(DBEntryBase *entry)
std::size_t hash_value(BgpAttr const &attr)
Definition: bgp_attr.cc:1259
virtual std::unique_ptr< DBEntry > AllocEntryStr(const std::string &key) const
Definition: inet_table.cc:37
ExtCommunityPtr ReplaceVrfRouteImportAndLocate(const ExtCommunity *src, const ExtCommunity::ExtCommunityValue &vit)
Definition: community.cc:856
BgpAttrPtr GetFabricAttributes(BgpRoute *rt, BgpAttrPtr attrp, const IPeer *peer)
Definition: inet_table.cc:313
InetTable(DB *db, const std::string &name)
Definition: inet_table.cc:22
as_t autonomous_system() const
Definition: bgp_server.h:205
BgpAttrPtr ReplaceOriginVnPathAndLocate(const BgpAttr *attr, OriginVnPathPtr ovnpath)
Definition: bgp_attr.cc:1338
#define MODULE_INITIALIZER(Func)
Definition: util.h:61
void SetAttr(const BgpAttrPtr attr, const BgpAttrPtr original_attr)
Definition: bgp_path.h:82
int index() const
virtual BgpRoute * TableFind(DBTablePartition *rtp, const DBRequestKey *prefix)
Definition: inet_table.cc:54
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
static bool is_origin_vn(const ExtCommunityValue &val)
Definition: community.h:193