OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bgp_attr_base.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #ifndef SRC_BGP_BGP_ATTR_BASE_H_
6 #define SRC_BGP_BGP_ATTR_BASE_H_
7 
8 #include <boost/functional/hash.hpp>
9 #include <boost/scoped_array.hpp>
10 #include <tbb/mutex.h>
11 
12 #include <set>
13 #include <string>
14 #include <utility>
15 #include <vector>
16 
17 #include "base/parse_object.h"
18 #include "base/task.h"
19 
20 class BgpAttr;
21 
22 class BgpAttribute : public ParseObject {
23 public:
24  enum Flag {
25  Optional = 1 << 7,
26  Transitive = 1 << 6,
27  Partial = 1 << 5,
28  ExtendedLength = 1 << 4
29  };
30  enum Code {
31  Reserved = 0,
32  Origin = 1,
33  AsPath = 2,
34  NextHop = 3,
36  LocalPref = 5,
45  As4Path = 17,
47  PmsiTunnel = 22,
50  OriginVnPath = 243,
51  };
52  enum Subcode {
53  OList = 1,
55  SourceRd = 3,
56  Esi = 4,
57  Params = 5,
58  LeafOList = 6,
60  };
61 
62  BgpAttribute() : code(0), subcode(0), flags(0) { }
63  BgpAttribute(uint8_t code, uint8_t flags)
64  : code(code), subcode(0), flags(flags) { }
65  BgpAttribute(uint8_t code, uint8_t subcode, uint8_t flags)
66  : code(code), subcode(subcode), flags(flags) { }
67  static const uint8_t FLAG_MASK = Optional|Transitive;
68  uint8_t code;
69  uint8_t subcode;
70  uint8_t flags;
71  /*
72  * Variable length attributes should return the size of the attribute
73  * for encoding purposes in order to set the ExtendedLength flag.
74  */
75  virtual size_t EncodeLength() const;
76  /*
77  * Helper method to compute flags used when encoding attributes.
78  */
79  uint8_t GetEncodeFlags() const;
80 
81  virtual std::string ToString() const;
82  virtual int CompareTo(const BgpAttribute &rhs) const;
83  virtual void ToCanonical(BgpAttr *attr) { }
84 };
85 
86 //
87 // Canonical structure used to exchange a single NLRI prefix between the
88 // common parser and the address family specific BGP code.
89 //
90 // ReadLabel and WriteLabel need a label offset because the label is at
91 // different locations in different NLRI.
92 //
93 // The prefix length is in bits.
94 // The type is relevant only for NLRI that have multiple route types e.g.
95 // erm-vpn and e-vpn.
96 //
97 struct BgpProtoPrefix : public ParseObject {
98  static const size_t kLabelSize;
99 
100  BgpProtoPrefix();
101 
102  uint32_t ReadLabel(size_t label_offset, bool is_vni = false) const;
103  void WriteLabel(size_t label_offset, uint32_t label, bool is_vni = false);
104 
105  std::vector<uint8_t> prefix;
107  uint8_t type;
108 };
109 
110 //
111 // Base class to manage BGP Path Attributes database. This class provides
112 // thread safe access to the data base.
113 //
114 // Lock contention can be tuned by varying the hash table size passed to the
115 // constructor.
116 //
117 // Attribute contents must be hashable via hash_value() and hashed using
118 // boost::hash_combine() to partition the attribute database.
119 //
120 template <class Type, class TypePtr, class TypeSpec, typename TypeCompare,
121  class TypeDB>
123 public:
124  explicit BgpPathAttributeDB(int hash_size = GetHashSize())
125  : hash_size_(hash_size),
126  set_(new Set[hash_size]),
127  mutex_(new tbb::mutex[hash_size]) {
128  }
129 
130  size_t Size() {
131  size_t size = 0;
132 
133  for (size_t i = 0; i < hash_size_; i++) {
134  tbb::mutex::scoped_lock lock(mutex_[i]);
135  size += set_[i].size();
136  }
137  return size;
138  }
139 
140  void Delete(Type *attr) {
141  size_t hash = HashCompute(attr);
142 
143  tbb::mutex::scoped_lock lock(mutex_[hash]);
144  assert(set_[hash].erase(attr));
145  }
146 
147  // Locate passed in attribute in the data base based on the attr ptr.
148  TypePtr Locate(Type *attr) {
149  return LocateInternal(attr);
150  }
151 
152  // Locate passed in attribute in the data base, based on the attr spec.
153  TypePtr Locate(const TypeSpec &spec) {
154  Type *attr = new Type(static_cast<TypeDB *>(this), spec);
155  return LocateInternal(attr);
156  }
157 
158 private:
159  const size_t HashCompute(Type *attr) const {
160  if (hash_size_ <= 1) return 0;
161 
162  size_t hash = 0;
163  boost::hash_combine(hash, *attr);
164  return hash % hash_size_;
165  }
166 
167  static size_t GetHashSize() {
168  char *str = getenv("BGP_PATH_ATTRIBUTE_DB_HASH_SIZE");
169 
170  // Use just one bucket for now.
171  if (!str) return 1;
172  return strtoul(str, NULL, 0);
173  }
174 
175  // This template safely retrieves an attribute entry from its data base.
176  // If the entry is not found, it is inserted into the database.
177  //
178  // If the entry is already present, then passed in entry is freed and
179  // existing entry is returned.
180  TypePtr LocateInternal(Type *attr) {
181  // Hash attribute contents to to avoid potential mutex contention.
182  size_t hash = HashCompute(attr);
183  while (true) {
184  // Grab mutex to keep db access thread safe.
185  tbb::mutex::scoped_lock lock(mutex_[hash]);
186  std::pair<typename Set::iterator, bool> ret;
187 
188  // Try to insert the passed entry into the database.
189  ret = set_[hash].insert(attr);
190 
191  // Take a reference to prevent this entry from getting deleted.
192  // Counter is automatically incremented, hence we get thread safety
193  // here.
194  int prev = intrusive_ptr_add_ref(*ret.first);
195 
196  // Check if passed in entry did get into the data base.
197  if (ret.second) {
198  // Take intrusive pointer, thereby incrementing the refcount.
199  TypePtr ptr = TypePtr(*ret.first);
200 
201  // Release redundant refcount taken above to protect this entry
202  // from getting deleted, as we have now bumped up refcount above
203  intrusive_ptr_del_ref(*ret.first);
204  return ptr;
205  }
206 
207  // Make sure that this entry, though in the database is not
208  // undergoing deletion. This can happen because attribute intrusive
209  // pointer is released without taking the mutex.
210  //
211  // If the previous refcount is 0, it implies that this entry is
212  // about to get deleted (after we release the mutex). In such
213  // cases, we retry inserting the passed attribute pointer into the
214  // data base.
215  if (prev > 0) {
216  // Free passed in attribute, as it is already in the database.
217  delete attr;
218 
219  // Take intrusive pointer, thereby incrementing the refcount.
220  TypePtr ptr = TypePtr(*ret.first);
221 
222  // Release redundant refcount taken above to protect this entry
223  // from getting deleted, as we have now bumped up refcount above
224  intrusive_ptr_del_ref(*ret.first);
225  return ptr;
226  }
227 
228  // Decrement the counter bumped up above as we can't use this entry
229  // which is about to be deleted. Instead, retry inserting the passed
230  // entry again, into the database.
231  intrusive_ptr_del_ref(*ret.first);
232  }
233 
234  assert(false);
235  return NULL;
236  }
237 
238  typedef std::set<Type *, TypeCompare> Set;
239  size_t hash_size_;
240  boost::scoped_array<Set> set_;
241  boost::scoped_array<tbb::mutex> mutex_;
242 };
243 
244 #endif // SRC_BGP_BGP_ATTR_BASE_H_
virtual std::string ToString() const
int intrusive_ptr_add_ref(const AsPath *cpath)
Definition: bgp_aspath.h:147
BgpAttribute(uint8_t code, uint8_t flags)
Definition: bgp_attr_base.h:63
BgpPathAttributeDB(int hash_size=GetHashSize())
TypePtr Locate(Type *attr)
void WriteLabel(size_t label_offset, uint32_t label, bool is_vni=false)
uint8_t flags
Definition: bgp_attr_base.h:70
uint32_t ReadLabel(size_t label_offset, bool is_vni=false) const
boost::scoped_array< tbb::mutex > mutex_
uint8_t GetEncodeFlags() const
TypePtr LocateInternal(Type *attr)
virtual size_t EncodeLength() const
BgpAttribute(uint8_t code, uint8_t subcode, uint8_t flags)
Definition: bgp_attr_base.h:65
virtual int CompareTo(const BgpAttribute &rhs) const
static const size_t kLabelSize
Definition: bgp_attr_base.h:98
std::vector< uint8_t > prefix
void Delete(Type *attr)
virtual void ToCanonical(BgpAttr *attr)
Definition: bgp_attr_base.h:83
const size_t HashCompute(Type *attr) const
int intrusive_ptr_del_ref(const AsPath *cpath)
Definition: bgp_aspath.h:151
boost::scoped_array< Set > set_
static const uint8_t FLAG_MASK
Definition: bgp_attr_base.h:67
static size_t GetHashSize()
TypePtr Locate(const TypeSpec &spec)
uint8_t subcode
Definition: bgp_attr_base.h:69
uint8_t code
Definition: bgp_attr_base.h:68