OpenSDN source code
flow_table.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #ifndef __AGENT_FLOW_TABLE_H__
6 #define __AGENT_FLOW_TABLE_H__
7 
8 #include <map>
9 #include <mutex>
10 
11 #if defined(__GNUC__)
12 #include "base/compiler.h"
13 #if __GNUC_PREREQ(4, 5)
14 #pragma GCC diagnostic push
15 #pragma GCC diagnostic ignored "-Wunused-result"
16 #endif
17 #endif
18 #include <boost/uuid/random_generator.hpp>
19 #if defined(__GNUC__)
20 #if __GNUC_PREREQ(4, 6)
21 #pragma GCC diagnostic pop
22 #endif
23 #endif
24 
25 #include <boost/uuid/uuid_io.hpp>
26 #include <boost/intrusive_ptr.hpp>
27 #include <base/util.h>
28 #include <base/address.h>
29 #include <db/db_table_walker.h>
30 #include <cmn/agent_cmn.h>
31 #include <oper/mirror_table.h>
32 #include <filter/traffic_action.h>
33 #include <filter/acl_entry.h>
34 #include <filter/acl.h>
35 #include <pkt/pkt_types.h>
36 #include <pkt/pkt_handler.h>
37 #include <pkt/pkt_init.h>
38 #include <pkt/pkt_flow_info.h>
39 #include <pkt/flow_entry.h>
40 #include <sandesh/sandesh_trace.h>
41 #include <oper/vn.h>
42 #include <oper/vm.h>
43 #include <oper/interface_common.h>
44 #include <oper/nexthop.h>
45 #include <oper/route_common.h>
46 #include <oper/sg.h>
47 #include <oper/vrf.h>
48 #include <filter/acl.h>
49 #include <sandesh/common/flow_types.h>
50 
51 class FlowStatsCollector;
52 class PktSandeshFlow;
53 class FetchFlowRecord;
54 class FlowEntry;
55 class FlowTable;
58 class FlowEvent;
59 class FlowEventKSync;
60 
61 #define FLOW_LOCK(flow, rflow, flow_event) \
62  bool is_flow_rflow_key_same = false; \
63  if (flow == rflow) { \
64  if (flow_event == FlowEvent::DELETE_FLOW) { \
65  assert(0); \
66  } \
67  is_flow_rflow_key_same = true; \
68  rflow = NULL; \
69  } \
70  std::unique_lock<std::mutex> lock1, lock2; \
71  if (flow && rflow) { \
72  auto l1 = std::unique_lock<std::mutex>(flow->mutex(), std::defer_lock); \
73  lock1.swap(l1); \
74  auto l2 = std::unique_lock<std::mutex>(rflow->mutex(), std::defer_lock); \
75  lock2.swap(l2); \
76  std::lock(lock1, lock2); \
77  } else if (flow) { \
78  auto l1 = std::unique_lock<std::mutex>(flow->mutex(), std::defer_lock); \
79  lock1.swap(l1); \
80  lock1.lock(); \
81  } else if (rflow) { \
82  auto l2 = std::unique_lock<std::mutex>(rflow->mutex(), std::defer_lock); \
83  lock2.swap(l2); \
84  lock2.lock(); \
85  } \
86  if (is_flow_rflow_key_same) { \
87  flow->MakeShortFlow(FlowEntry::SHORT_SAME_FLOW_RFLOW_KEY); \
88  }
89 
91 // Class to manage free-list of flow-entries
92 // Flow allocation can happen from multiple threads. In scaled scenarios
93 // allocation of flow-entries in multi-thread environment adds overheads.
94 // The FlowEntryFreeList helps to maintain a per task free-list. Alloc/Free
95 // can happen withou lock.
96 //
97 // Alloc and Free happens in a chunk. Alloc/Free are done based on thresholds
98 // in task context of the corresponding flow-table
101 public:
102  static const uint32_t kInitCount = (25 * 1000);
103  static const uint32_t kTestInitCount = (5 * 1000);
104  static const uint32_t kGrowSize = (1 * 1000);
105  static const uint32_t kMinThreshold = (4 * 1000);
106  static const uint32_t kMaxThreshold = (100 * 1000);
107 
108  typedef boost::intrusive::member_hook<FlowEntry,
109  boost::intrusive::list_member_hook<>,
111  typedef boost::intrusive::list<FlowEntry, Node> FreeList;
112 
114  virtual ~FlowEntryFreeList();
115 
116  FlowEntry *Allocate(const FlowKey &key);
117  void Free(FlowEntry *flow);
118  void Grow();
119  uint32_t max_count() const { return max_count_; }
120  uint32_t free_count() const { return free_list_.size(); }
121  uint32_t alloc_count() const { return (max_count_ - free_list_.size()); }
122  uint32_t total_alloc() const { return total_alloc_; }
123  uint32_t total_free() const { return total_free_; }
124 private:
126  uint32_t max_count_;
128  uint64_t total_alloc_;
129  uint64_t total_free_;
132 };
133 
135 // Flow addition is a two step process.
136 // - FlowHandler :
137 // Flow is created in this context (file pkt_flow_info.cc).
138 // There can potentially be multiple FlowHandler task running in parallel
139 // - FlowTable :
140 // This module will maintain a tree of all flows created. It is also
141 // responsible to generate KSync events. It is run in a single task context
142 //
143 // Functionality of FlowTable:
144 // 1. Manage flow_entry_map_ which contains all flows
145 // 2. Enforce the per-VM flow limits
146 // 3. Generate events to KSync and FlowMgmt modueles
148 struct FlowTaskMsg : public InterTaskMsg {
150  virtual ~FlowTaskMsg() { }
151 
153 };
154 
156  bool operator()(const FlowKey &lhs, const FlowKey &rhs) const {
157  const FlowKey &lhs_base = static_cast<const FlowKey &>(lhs);
158  return lhs_base.IsLess(rhs);
159  }
160 };
161 
162 class FlowTable {
163 public:
164  static const uint32_t kPortNatFlowTableInstance = 0;
165  static const uint32_t kInvalidFlowTableInstance = 0xFF;
166 
167  typedef std::map<FlowKey, FlowEntry *, Inet4FlowKeyCmp> FlowEntryMap;
168  typedef std::pair<FlowKey, FlowEntry *> FlowEntryMapPair;
169  typedef boost::function<bool(FlowEntry *flow)> FlowEntryCb;
170  typedef std::vector<FlowEntryPtr> FlowIndexTree;
171 
173  uint32_t flow_index;
175  uint64_t timestamp;
176 
177  LinkLocalFlowInfo(uint32_t index, const FlowKey &key, uint64_t t) :
178  flow_index(index), flow_key(key), timestamp(t) {}
179  };
180  typedef std::map<int, LinkLocalFlowInfo> LinkLocalFlowInfoMap;
181  typedef std::pair<int, LinkLocalFlowInfo> LinkLocalFlowInfoPair;
182 
183  FlowTable(Agent *agent, uint16_t table_index);
184  virtual ~FlowTable();
185 
186  void Init();
187  void InitDone();
188  void Shutdown();
189 
190  // Accessor routines
193 
194  // Table managment routines
195  FlowEntry *Locate(FlowEntry *flow, uint64_t t);
196  FlowEntry *Find(const FlowKey &key);
197  void Add(FlowEntry *flow, FlowEntry *rflow);
198  void Update(FlowEntry *flow, FlowEntry *rflow);
199  //bool Delete(const FlowKey &flow_key);
200  bool Delete(const FlowKey &key, bool del_reverse_flow);
201  void DeleteAll();
202  // Test code only used method
203  void DeleteFlow(const AclDBEntry *acl, const FlowKey &key,
204  AclEntryIDList &id_list);
205 
206  // Accessor routines
207  Agent *agent() const { return agent_; }
208  uint16_t table_index() const { return table_index_; }
209  size_t Size() { return flow_entry_map_.size(); }
210  FlowTable::FlowEntryMap::iterator begin() {
211  return flow_entry_map_.begin();
212  }
213  FlowTable::FlowEntryMap::iterator end() {
214  return flow_entry_map_.end();
215  }
216 
219  }
220  void AddLinkLocalFlowInfo(int fd, uint32_t index, const FlowKey &key,
221  const uint64_t timestamp);
222  void DelLinkLocalFlowInfo(int fd);
223 
224  static const char *TaskName() { return kTaskFlowEvent; }
225  // Sandesh routines
226  void Copy(FlowEntry *lhs, FlowEntry *rhs, bool update);
227  void SetAclFlowSandeshData(const AclDBEntry *acl, AclFlowResp &data,
228  const int last_count);
229  void SetAceSandeshData(const AclDBEntry *acl, AclFlowCountResp &data,
230  int ace_id);
231 
232  void RecomputeFlow(FlowEntry *flow);
233  void DeleteMessage(FlowEntry *flow);
234 
235  void DeleteVrf(VrfEntry *vrf);
236 
237  void HandleRevaluateDBEntry(const DBEntry *entry, FlowEntry *flow,
238  bool active_flow, bool deleted_flow);
239  void HandleKSyncError(FlowEntry *flow, FlowTableKSyncEntry *ksync_entry,
240  int ksync_error, uint32_t flow_handle,
241  uint32_t gen_id);
243 
244  void UpdateKSync(FlowEntry *flow, bool update);
245  void DeleteKSync(FlowEntry *flow);
246 
247  // Free list
248  void GrowFreeList();
250 
251  void ProcessKSyncFlowEvent(const FlowEventKSync *req, FlowEntry *flow);
252  bool ProcessFlowEvent(const FlowEvent *req, FlowEntry *flow,
253  FlowEntry *rflow);
254  void PopulateFlowEntriesUsingKey(const FlowKey &key, bool reverse_flow,
255  FlowEntry** flow, FlowEntry** rflow);
256 
257  // Concurrency check to ensure all flow-table and free-list manipulations
258  // are done from FlowEvent task context only
259  //exception: freelist free function can be accessed by flow logging task
260  bool ConcurrencyCheck(int task_id, bool check_task_instance);
261  bool ConcurrencyCheck(int task_id);
262  int flow_task_id() const { return flow_task_id_; }
265  int flow_ksync_task_id() const { return flow_ksync_task_id_; }
267  static void GetFlowSandeshActionParams(const FlowAction &action_info,
268  std::string &action_str);
269 
270  friend class FlowStatsCollector;
271  friend class PktSandeshFlow;
272  friend class PktSandeshFlowStats;
273  friend class FetchFlowRecord;
274  friend class PktFlowInfo;
275  friend void intrusive_ptr_release(FlowEntry *fe);
276 private:
277  void DisableKSyncSend(FlowEntry *flow, uint32_t evict_gen_id);
278  bool IsEvictedFlow(const FlowKey &key);
279 
280  void DeleteFlowUveInfo(FlowEntry *fe);
281 
282  void DeleteInternal(FlowEntry *fe, uint64_t t, const RevFlowDepParams &p);
283  void DeleteFlowInfo(FlowEntry *fe, const RevFlowDepParams &params);
284 
285  void AddFlowInfo(FlowEntry *fe);
286  void UpdateReverseFlow(FlowEntry *flow, FlowEntry *rflow);
287 
288  void UpdateUnLocked(FlowEntry *flow, FlowEntry *rflow);
289  void AddInternal(FlowEntry *flow, FlowEntry *new_flow, FlowEntry *rflow,
290  FlowEntry *new_rflow, bool fwd_flow_update,
291  bool rev_flow_update);
292  void Add(FlowEntry *flow, FlowEntry *new_flow, FlowEntry *rflow,
293  FlowEntry *new_rflow, bool fwd_flow_update, bool rev_flow_update);
294  void EvictFlow(FlowEntry *flow, FlowEntry *rflow, uint32_t evict_gen_id);
295  bool DeleteFlows(FlowEntry *flow, FlowEntry *rflow);
296  bool DeleteUnLocked(const FlowKey &key, bool del_reverse_flow);
297  bool DeleteUnLocked(bool del_reverse_flow, FlowEntry *flow,
298  FlowEntry *rflow);
299  void ReleasePort(FlowEntry *flow, bool evict);
300 
302  boost::uuids::random_generator rand_gen_;
303  uint16_t table_index_;
306 
308  // maintain the linklocal flow info against allocated fd, debug purpose only
311  std::mutex mutex_;
318 };
319 
320 struct FlowEntryCmp {
321  bool operator()(const FlowEntryPtr &l, const FlowEntryPtr &r) {
322  FlowEntry *lhs = l.get();
323  FlowEntry *rhs = r.get();
324 
325  return (lhs < rhs);
326  }
327 };
328 
329 typedef std::set<FlowEntryPtr, FlowEntryCmp> FlowEntryTree;
331 extern void SetActionStr(const FlowAction &, std::vector<ActionStr> &);
332 
333 #define FLOW_TRACE(obj, ...)\
334 do {\
335  Flow##obj::TraceMsg(FlowTraceBuf, __FILE__, __LINE__, ##__VA_ARGS__);\
336 } while (false)
337 
338 #endif
std::vector< AclEntryID > AclEntryIDList
Definition: acl_entry.h:85
#define kTaskFlowEvent
Definition: agent.h:323
Definition: acl.h:91
Definition: agent.h:360
static const uint32_t kTestInitCount
Definition: flow_table.h:103
DISALLOW_COPY_AND_ASSIGN(FlowEntryFreeList)
uint64_t total_alloc_
Definition: flow_table.h:128
virtual ~FlowEntryFreeList()
Definition: flow_table.cc:972
static const uint32_t kMaxThreshold
Definition: flow_table.h:106
boost::intrusive::member_hook< FlowEntry, boost::intrusive::list_member_hook<>, &FlowEntry::free_list_node_ > Node
Definition: flow_table.h:110
FreeList free_list_
Definition: flow_table.h:130
boost::intrusive::list< FlowEntry, Node > FreeList
Definition: flow_table.h:111
uint32_t alloc_count() const
Definition: flow_table.h:121
FlowEntry * Allocate(const FlowKey &key)
Definition: flow_table.cc:994
static const uint32_t kMinThreshold
Definition: flow_table.h:105
uint32_t total_free() const
Definition: flow_table.h:123
FlowTable * table_
Definition: flow_table.h:125
void Free(FlowEntry *flow)
Definition: flow_table.cc:1016
static const uint32_t kInitCount
Definition: flow_table.h:102
uint32_t free_count() const
Definition: flow_table.h:120
uint64_t total_free_
Definition: flow_table.h:129
FlowEntryFreeList(FlowTable *table)
Definition: flow_table.cc:958
uint32_t max_count() const
Definition: flow_table.h:119
uint32_t max_count_
Definition: flow_table.h:126
static const uint32_t kGrowSize
Definition: flow_table.h:104
uint32_t total_alloc() const
Definition: flow_table.h:122
boost::intrusive::list_member_hook free_list_node_
Definition: flow_entry.h:843
const LinkLocalFlowInfoMap & linklocal_flow_info_map()
Definition: flow_table.h:217
friend class FetchFlowRecord
Definition: flow_table.h:273
bool DeleteFlows(FlowEntry *flow, FlowEntry *rflow)
Definition: flow_table.cc:327
Agent * agent_
Definition: flow_table.h:301
void SetAclFlowSandeshData(const AclDBEntry *acl, AclFlowResp &data, const int last_count)
void Copy(FlowEntry *lhs, FlowEntry *rhs, bool update)
Definition: flow_table.cc:133
void Init()
Definition: flow_table.cc:77
int flow_ksync_task_id() const
Definition: flow_table.h:265
void Add(FlowEntry *flow, FlowEntry *new_flow, FlowEntry *rflow, FlowEntry *new_rflow, bool fwd_flow_update, bool rev_flow_update)
FlowEntry * Find(const FlowKey &key)
Definition: flow_table.cc:121
Agent * agent() const
Definition: flow_table.h:207
static void GetFlowSandeshActionParams(const FlowAction &action_info, std::string &action_str)
Definition: flow_table.cc:937
FlowTable::FlowEntryMap::iterator begin()
Definition: flow_table.h:210
FlowEntryFreeList free_list_
Definition: flow_table.h:310
int flow_logging_task_id() const
Definition: flow_table.h:266
FlowTableKSyncObject * ksync_object_
Definition: flow_table.h:304
void DelLinkLocalFlowInfo(int fd)
Definition: flow_table.cc:759
void RecomputeFlow(FlowEntry *flow)
Definition: flow_table.cc:504
void Shutdown()
Definition: flow_table.cc:90
size_t Size()
Definition: flow_table.h:209
int flow_delete_task_id() const
Definition: flow_table.h:264
std::map< FlowKey, FlowEntry *, Inet4FlowKeyCmp > FlowEntryMap
Definition: flow_table.h:167
void AddInternal(FlowEntry *flow, FlowEntry *new_flow, FlowEntry *rflow, FlowEntry *new_rflow, bool fwd_flow_update, bool rev_flow_update)
Definition: flow_table.cc:186
friend void intrusive_ptr_release(FlowEntry *fe)
Definition: flow_entry.cc:571
FlowEntry * Locate(FlowEntry *flow, uint64_t t)
Definition: flow_table.cc:147
void Add(FlowEntry *flow, FlowEntry *rflow)
Definition: flow_table.cc:160
int flow_update_task_id() const
Definition: flow_table.h:263
static const uint32_t kInvalidFlowTableInstance
Definition: flow_table.h:165
void ReleasePort(FlowEntry *flow, bool evict)
Definition: flow_table.cc:523
void PopulateFlowEntriesUsingKey(const FlowKey &key, bool reverse_flow, FlowEntry **flow, FlowEntry **rflow)
Definition: flow_table.cc:353
std::mutex mutex_
Definition: flow_table.h:311
void DeleteAll()
Definition: flow_table.cc:414
void DisableKSyncSend(FlowEntry *flow, uint32_t evict_gen_id)
Definition: flow_table.cc:738
LinkLocalFlowInfoMap linklocal_flow_info_map_
Definition: flow_table.h:309
bool Delete(const FlowKey &key, bool del_reverse_flow)
Definition: flow_table.cc:405
int flow_task_id_
Definition: flow_table.h:312
void set_ksync_object(FlowTableKSyncObject *obj)
Definition: flow_table.h:191
void EvictFlow(FlowEntry *flow, FlowEntry *rflow, uint32_t evict_gen_id)
Definition: flow_table.cc:532
FlowTable(Agent *agent, uint16_t table_index)
Definition: flow_table.cc:59
bool ProcessFlowEvent(const FlowEvent *req, FlowEntry *flow, FlowEntry *rflow)
Definition: flow_table.cc:835
FlowIndexTree flow_index_tree_
Definition: flow_table.h:307
uint16_t table_index() const
Definition: flow_table.h:208
void UpdateUnLocked(FlowEntry *flow, FlowEntry *rflow)
void ProcessKSyncFlowEvent(const FlowEventKSync *req, FlowEntry *flow)
Definition: flow_table.cc:769
void DeleteKSync(FlowEntry *flow)
Definition: flow_table.cc:722
static const uint32_t kPortNatFlowTableInstance
Definition: flow_table.h:164
void UpdateReverseFlow(FlowEntry *flow, FlowEntry *rflow)
Definition: flow_table.cc:432
virtual ~FlowTable()
Definition: flow_table.cc:73
void DeleteFlowUveInfo(FlowEntry *fe)
Definition: flow_table.cc:481
void UpdateKSync(FlowEntry *flow, bool update)
Definition: flow_table.cc:727
void HandleKSyncError(FlowEntry *flow, FlowTableKSyncEntry *ksync_entry, int ksync_error, uint32_t flow_handle, uint32_t gen_id)
Definition: flow_table.cc:634
void DeleteFlowInfo(FlowEntry *fe, const RevFlowDepParams &params)
Definition: flow_table.cc:492
FlowTableKSyncObject * ksync_object() const
Definition: flow_table.h:192
int flow_ksync_task_id_
Definition: flow_table.h:315
FlowEntryFreeList * free_list()
Definition: flow_table.h:249
DISALLOW_COPY_AND_ASSIGN(FlowTable)
boost::uuids::random_generator rand_gen_
Definition: flow_table.h:302
int flow_task_id() const
Definition: flow_table.h:262
boost::uuids::uuid rand_gen()
Definition: flow_table.cc:499
std::vector< FlowEntryPtr > FlowIndexTree
Definition: flow_table.h:170
boost::function< bool(FlowEntry *flow)> FlowEntryCb
Definition: flow_table.h:169
bool DeleteUnLocked(const FlowKey &key, bool del_reverse_flow)
Definition: flow_table.cc:397
void DeleteInternal(FlowEntry *fe, uint64_t t, const RevFlowDepParams &p)
Definition: flow_table.cc:308
std::map< int, LinkLocalFlowInfo > LinkLocalFlowInfoMap
Definition: flow_table.h:180
void GrowFreeList()
Definition: flow_table.cc:953
FlowEntryMap flow_entry_map_
Definition: flow_table.h:305
int flow_logging_task_id_
Definition: flow_table.h:316
void DeleteVrf(VrfEntry *vrf)
bool IsEvictedFlow(const FlowKey &key)
void InitDone()
Definition: flow_table.cc:87
std::pair< int, LinkLocalFlowInfo > LinkLocalFlowInfoPair
Definition: flow_table.h:181
int flow_delete_task_id_
Definition: flow_table.h:314
static const char * TaskName()
Definition: flow_table.h:224
std::pair< FlowKey, FlowEntry * > FlowEntryMapPair
Definition: flow_table.h:168
uint16_t table_index_
Definition: flow_table.h:303
void AddLinkLocalFlowInfo(int fd, uint32_t index, const FlowKey &key, const uint64_t timestamp)
Definition: flow_table.cc:746
void DeleteFlow(const AclDBEntry *acl, const FlowKey &key, AclEntryIDList &id_list)
void Update(FlowEntry *flow, FlowEntry *rflow)
Definition: flow_table.cc:169
void HandleRevaluateDBEntry(const DBEntry *entry, FlowEntry *flow, bool active_flow, bool deleted_flow)
Definition: flow_table.cc:544
void AddFlowInfo(FlowEntry *fe)
Definition: flow_table.cc:488
void SetAceSandeshData(const AclDBEntry *acl, AclFlowCountResp &data, int ace_id)
void DeleteMessage(FlowEntry *flow)
Definition: flow_table.cc:519
int flow_update_task_id_
Definition: flow_table.h:313
bool ConcurrencyCheck(int task_id, bool check_task_instance)
Definition: flow_table.cc:96
FlowTable::FlowEntryMap::iterator end()
Definition: flow_table.h:213
Definition: vrf.h:89
boost::intrusive_ptr< FlowEntry > FlowEntryPtr
Definition: flow_entry.h:125
void SetActionStr(const FlowAction &, std::vector< ActionStr > &)
Definition: flow_entry.cc:3068
std::set< FlowEntryPtr, FlowEntryCmp > FlowEntryTree
Definition: flow_table.h:329
SandeshTraceBufferPtr FlowTraceBuf
boost::shared_ptr< TraceBuffer< SandeshTrace > > SandeshTraceBufferPtr
Definition: sandesh_trace.h:18
Definition: acl.h:34
bool operator()(const FlowEntryPtr &l, const FlowEntryPtr &r)
Definition: flow_table.h:321
bool IsLess(const FlowKey &key) const
Definition: flow_entry.h:154
LinkLocalFlowInfo(uint32_t index, const FlowKey &key, uint64_t t)
Definition: flow_table.h:177
FlowEntryPtr fe_ptr
Definition: flow_table.h:152
virtual ~FlowTaskMsg()
Definition: flow_table.h:150
FlowTaskMsg(FlowEntry *fe)
Definition: flow_table.h:149
bool operator()(const FlowKey &lhs, const FlowKey &rhs) const
Definition: flow_table.h:156
boost::uuids::uuid uuid