OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 #if defined(__GNUC__)
10 #include "base/compiler.h"
11 #if __GNUC_PREREQ(4, 5)
12 #pragma GCC diagnostic push
13 #pragma GCC diagnostic ignored "-Wunused-result"
14 #endif
15 #endif
16 #include <boost/uuid/random_generator.hpp>
17 #if defined(__GNUC__)
18 #if __GNUC_PREREQ(4, 6)
19 #pragma GCC diagnostic pop
20 #endif
21 #endif
22 
23 #include <boost/uuid/uuid_io.hpp>
24 #include <boost/intrusive_ptr.hpp>
25 #include <tbb/atomic.h>
26 #include <tbb/mutex.h>
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  tbb::mutex tmp_mutex1, tmp_mutex2, *mutex_ptr_1, *mutex_ptr_2; \
71  FlowTable::GetMutexSeq(flow ? flow->mutex() : tmp_mutex1, \
72  rflow ? rflow->mutex() : tmp_mutex2, \
73  &mutex_ptr_1, &mutex_ptr_2); \
74  tbb::mutex::scoped_lock lock1(*mutex_ptr_1); \
75  tbb::mutex::scoped_lock lock2(*mutex_ptr_2); \
76  if (is_flow_rflow_key_same) { \
77  flow->MakeShortFlow(FlowEntry::SHORT_SAME_FLOW_RFLOW_KEY); \
78  }
79 
81 // Class to manage free-list of flow-entries
82 // Flow allocation can happen from multiple threads. In scaled scenarios
83 // allocation of flow-entries in multi-thread environment adds overheads.
84 // The FlowEntryFreeList helps to maintain a per task free-list. Alloc/Free
85 // can happen withou lock.
86 //
87 // Alloc and Free happens in a chunk. Alloc/Free are done based on thresholds
88 // in task context of the corresponding flow-table
91 public:
92  static const uint32_t kInitCount = (25 * 1000);
93  static const uint32_t kTestInitCount = (5 * 1000);
94  static const uint32_t kGrowSize = (1 * 1000);
95  static const uint32_t kMinThreshold = (4 * 1000);
96  static const uint32_t kMaxThreshold = (100 * 1000);
97 
98  typedef boost::intrusive::member_hook<FlowEntry,
99  boost::intrusive::list_member_hook<>,
101  typedef boost::intrusive::list<FlowEntry, Node> FreeList;
102 
104  virtual ~FlowEntryFreeList();
105 
106  FlowEntry *Allocate(const FlowKey &key);
107  void Free(FlowEntry *flow);
108  void Grow();
109  uint32_t max_count() const { return max_count_; }
110  uint32_t free_count() const { return free_list_.size(); }
111  uint32_t alloc_count() const { return (max_count_ - free_list_.size()); }
112  uint32_t total_alloc() const { return total_alloc_; }
113  uint32_t total_free() const { return total_free_; }
114 private:
116  uint32_t max_count_;
118  uint64_t total_alloc_;
119  uint64_t total_free_;
122 };
123 
125 // Flow addition is a two step process.
126 // - FlowHandler :
127 // Flow is created in this context (file pkt_flow_info.cc).
128 // There can potentially be multiple FlowHandler task running in parallel
129 // - FlowTable :
130 // This module will maintain a tree of all flows created. It is also
131 // responsible to generate KSync events. It is run in a single task context
132 //
133 // Functionality of FlowTable:
134 // 1. Manage flow_entry_map_ which contains all flows
135 // 2. Enforce the per-VM flow limits
136 // 3. Generate events to KSync and FlowMgmt modueles
138 struct FlowTaskMsg : public InterTaskMsg {
140  virtual ~FlowTaskMsg() { }
141 
143 };
144 
146  bool operator()(const FlowKey &lhs, const FlowKey &rhs) const {
147  const FlowKey &lhs_base = static_cast<const FlowKey &>(lhs);
148  return lhs_base.IsLess(rhs);
149  }
150 };
151 
152 class FlowTable {
153 public:
154  static const uint32_t kPortNatFlowTableInstance = 0;
155  static const uint32_t kInvalidFlowTableInstance = 0xFF;
156 
157  typedef std::map<FlowKey, FlowEntry *, Inet4FlowKeyCmp> FlowEntryMap;
158  typedef std::pair<FlowKey, FlowEntry *> FlowEntryMapPair;
159  typedef boost::function<bool(FlowEntry *flow)> FlowEntryCb;
160  typedef std::vector<FlowEntryPtr> FlowIndexTree;
161 
163  uint32_t flow_index;
165  uint64_t timestamp;
166 
167  LinkLocalFlowInfo(uint32_t index, const FlowKey &key, uint64_t t) :
168  flow_index(index), flow_key(key), timestamp(t) {}
169  };
170  typedef std::map<int, LinkLocalFlowInfo> LinkLocalFlowInfoMap;
171  typedef std::pair<int, LinkLocalFlowInfo> LinkLocalFlowInfoPair;
172 
173  FlowTable(Agent *agent, uint16_t table_index);
174  virtual ~FlowTable();
175 
176  void Init();
177  void InitDone();
178  void Shutdown();
179 
180  // Accessor routines
183 
184  // Table managment routines
185  FlowEntry *Locate(FlowEntry *flow, uint64_t t);
186  FlowEntry *Find(const FlowKey &key);
187  void Add(FlowEntry *flow, FlowEntry *rflow);
188  void Update(FlowEntry *flow, FlowEntry *rflow);
189  //bool Delete(const FlowKey &flow_key);
190  bool Delete(const FlowKey &key, bool del_reverse_flow);
191  void DeleteAll();
192  // Test code only used method
193  void DeleteFlow(const AclDBEntry *acl, const FlowKey &key,
194  AclEntryIDList &id_list);
195 
196  // Accessor routines
197  Agent *agent() const { return agent_; }
198  uint16_t table_index() const { return table_index_; }
199  size_t Size() { return flow_entry_map_.size(); }
200  FlowTable::FlowEntryMap::iterator begin() {
201  return flow_entry_map_.begin();
202  }
203  FlowTable::FlowEntryMap::iterator end() {
204  return flow_entry_map_.end();
205  }
206 
209  }
210  void AddLinkLocalFlowInfo(int fd, uint32_t index, const FlowKey &key,
211  const uint64_t timestamp);
212  void DelLinkLocalFlowInfo(int fd);
213 
214  static const char *TaskName() { return kTaskFlowEvent; }
215  // Sandesh routines
216  void Copy(FlowEntry *lhs, FlowEntry *rhs, bool update);
217  void SetAclFlowSandeshData(const AclDBEntry *acl, AclFlowResp &data,
218  const int last_count);
219  void SetAceSandeshData(const AclDBEntry *acl, AclFlowCountResp &data,
220  int ace_id);
221 
222  void RecomputeFlow(FlowEntry *flow);
223  void DeleteMessage(FlowEntry *flow);
224 
225  void DeleteVrf(VrfEntry *vrf);
226 
227  void HandleRevaluateDBEntry(const DBEntry *entry, FlowEntry *flow,
228  bool active_flow, bool deleted_flow);
229  void HandleKSyncError(FlowEntry *flow, FlowTableKSyncEntry *ksync_entry,
230  int ksync_error, uint32_t flow_handle,
231  uint32_t gen_id);
233 
234  void UpdateKSync(FlowEntry *flow, bool update);
235  void DeleteKSync(FlowEntry *flow);
236 
237  // Free list
238  void GrowFreeList();
240 
241  void ProcessKSyncFlowEvent(const FlowEventKSync *req, FlowEntry *flow);
242  bool ProcessFlowEvent(const FlowEvent *req, FlowEntry *flow,
243  FlowEntry *rflow);
244  void PopulateFlowEntriesUsingKey(const FlowKey &key, bool reverse_flow,
245  FlowEntry** flow, FlowEntry** rflow);
246 
247  // Concurrency check to ensure all flow-table and free-list manipulations
248  // are done from FlowEvent task context only
249  //exception: freelist free function can be accessed by flow logging task
250  bool ConcurrencyCheck(int task_id, bool check_task_instance);
251  bool ConcurrencyCheck(int task_id);
252  int flow_task_id() const { return flow_task_id_; }
255  int flow_ksync_task_id() const { return flow_ksync_task_id_; }
257  static void GetMutexSeq(tbb::mutex &mutex1, tbb::mutex &mutex2,
258  tbb::mutex **mutex_ptr_1, tbb::mutex **mutex_ptr_2);
259  static void GetFlowSandeshActionParams(const FlowAction &action_info,
260  std::string &action_str);
261 
262  friend class FlowStatsCollector;
263  friend class PktSandeshFlow;
264  friend class PktSandeshFlowStats;
265  friend class FetchFlowRecord;
266  friend class PktFlowInfo;
267  friend void intrusive_ptr_release(FlowEntry *fe);
268 private:
269  void DisableKSyncSend(FlowEntry *flow, uint32_t evict_gen_id);
270  bool IsEvictedFlow(const FlowKey &key);
271 
272  void DeleteFlowUveInfo(FlowEntry *fe);
273 
274  void DeleteInternal(FlowEntry *fe, uint64_t t, const RevFlowDepParams &p);
275  void DeleteFlowInfo(FlowEntry *fe, const RevFlowDepParams &params);
276 
277  void AddFlowInfo(FlowEntry *fe);
278  void UpdateReverseFlow(FlowEntry *flow, FlowEntry *rflow);
279 
280  void UpdateUnLocked(FlowEntry *flow, FlowEntry *rflow);
281  void AddInternal(FlowEntry *flow, FlowEntry *new_flow, FlowEntry *rflow,
282  FlowEntry *new_rflow, bool fwd_flow_update,
283  bool rev_flow_update);
284  void Add(FlowEntry *flow, FlowEntry *new_flow, FlowEntry *rflow,
285  FlowEntry *new_rflow, bool fwd_flow_update, bool rev_flow_update);
286  void EvictFlow(FlowEntry *flow, FlowEntry *rflow, uint32_t evict_gen_id);
287  bool DeleteFlows(FlowEntry *flow, FlowEntry *rflow);
288  bool DeleteUnLocked(const FlowKey &key, bool del_reverse_flow);
289  bool DeleteUnLocked(bool del_reverse_flow, FlowEntry *flow,
290  FlowEntry *rflow);
291  void ReleasePort(FlowEntry *flow, bool evict);
292 
294  boost::uuids::random_generator rand_gen_;
295  uint16_t table_index_;
298 
300  // maintain the linklocal flow info against allocated fd, debug purpose only
303  tbb::mutex mutex_;
310 };
311 
312 struct FlowEntryCmp {
313  bool operator()(const FlowEntryPtr &l, const FlowEntryPtr &r) {
314  FlowEntry *lhs = l.get();
315  FlowEntry *rhs = r.get();
316 
317  return (lhs < rhs);
318  }
319 };
320 
321 typedef std::set<FlowEntryPtr, FlowEntryCmp> FlowEntryTree;
323 extern void SetActionStr(const FlowAction &, std::vector<ActionStr> &);
324 
325 #define FLOW_TRACE(obj, ...)\
326 do {\
327  Flow##obj::TraceMsg(FlowTraceBuf, __FILE__, __LINE__, ##__VA_ARGS__);\
328 } while (false)
329 
330 #endif
FlowIndexTree flow_index_tree_
Definition: flow_table.h:299
bool IsEvictedFlow(const FlowKey &key)
std::set< FlowEntryPtr, FlowEntryCmp > FlowEntryTree
Definition: flow_table.h:321
boost::uuids::uuid rand_gen()
Definition: flow_table.cc:514
LinkLocalFlowInfoMap linklocal_flow_info_map_
Definition: flow_table.h:301
bool operator()(const FlowKey &lhs, const FlowKey &rhs) const
Definition: flow_table.h:146
bool ConcurrencyCheck(int task_id, bool check_task_instance)
Definition: flow_table.cc:95
boost::function< bool(FlowEntry *flow)> FlowEntryCb
Definition: flow_table.h:159
void DelLinkLocalFlowInfo(int fd)
Definition: flow_table.cc:766
FlowEntryMap flow_entry_map_
Definition: flow_table.h:297
void DeleteAll()
Definition: flow_table.cc:429
static const char * TaskName()
Definition: flow_table.h:214
bool DeleteUnLocked(const FlowKey &key, bool del_reverse_flow)
Definition: flow_table.cc:412
void DeleteFlowInfo(FlowEntry *fe, const RevFlowDepParams &params)
Definition: flow_table.cc:507
Definition: vrf.h:86
FlowEntryFreeList free_list_
Definition: flow_table.h:302
bool IsLess(const FlowKey &key) const
Definition: flow_entry.h:154
int flow_task_id() const
Definition: flow_table.h:252
bool Delete(const FlowKey &key, bool del_reverse_flow)
Definition: flow_table.cc:420
#define kTaskFlowEvent
Definition: agent.h:321
static const uint32_t kMinThreshold
Definition: flow_table.h:95
void SetAceSandeshData(const AclDBEntry *acl, AclFlowCountResp &data, int ace_id)
void DeleteFlow(const AclDBEntry *acl, const FlowKey &key, AclEntryIDList &id_list)
static const uint32_t kInitCount
Definition: flow_table.h:92
FlowEntryPtr fe_ptr
Definition: flow_table.h:142
static const uint32_t kPortNatFlowTableInstance
Definition: flow_table.h:154
boost::uuids::random_generator rand_gen_
Definition: flow_table.h:294
FreeList free_list_
Definition: flow_table.h:120
bool operator()(const FlowEntryPtr &l, const FlowEntryPtr &r)
Definition: flow_table.h:313
Agent * agent() const
Definition: flow_table.h:197
void HandleKSyncError(FlowEntry *flow, FlowTableKSyncEntry *ksync_entry, int ksync_error, uint32_t flow_handle, uint32_t gen_id)
Definition: flow_table.cc:649
std::vector< FlowEntryPtr > FlowIndexTree
Definition: flow_table.h:160
int flow_update_task_id() const
Definition: flow_table.h:253
tbb::mutex mutex_
Definition: flow_table.h:303
std::vector< AclEntryID > AclEntryIDList
Definition: acl_entry.h:85
FlowEntry * Locate(FlowEntry *flow, uint64_t t)
Definition: flow_table.cc:162
static void GetMutexSeq(tbb::mutex &mutex1, tbb::mutex &mutex2, tbb::mutex **mutex_ptr_1, tbb::mutex **mutex_ptr_2)
Definition: flow_table.cc:122
void Shutdown()
Definition: flow_table.cc:89
boost::uuids::uuid uuid
static const uint32_t kTestInitCount
Definition: flow_table.h:93
void DeleteKSync(FlowEntry *flow)
Definition: flow_table.cc:729
void set_ksync_object(FlowTableKSyncObject *obj)
Definition: flow_table.h:181
uint16_t table_index() const
Definition: flow_table.h:198
void HandleRevaluateDBEntry(const DBEntry *entry, FlowEntry *flow, bool active_flow, bool deleted_flow)
Definition: flow_table.cc:559
int flow_task_id_
Definition: flow_table.h:304
FlowTable(Agent *agent, uint16_t table_index)
Definition: flow_table.cc:58
void SetActionStr(const FlowAction &action_info, std::vector< ActionStr > &action_str_l)
Definition: flow_entry.cc:3015
void DeleteInternal(FlowEntry *fe, uint64_t t, const RevFlowDepParams &p)
Definition: flow_table.cc:323
boost::shared_ptr< TraceBuffer< SandeshTrace > > SandeshTraceBufferPtr
Definition: sandesh_trace.h:18
std::pair< FlowKey, FlowEntry * > FlowEntryMapPair
Definition: flow_table.h:158
int flow_delete_task_id_
Definition: flow_table.h:306
uint32_t total_alloc() const
Definition: flow_table.h:112
int flow_ksync_task_id() const
Definition: flow_table.h:255
static const uint32_t kMaxThreshold
Definition: flow_table.h:96
void UpdateKSync(FlowEntry *flow, bool update)
Definition: flow_table.cc:734
bool ProcessFlowEvent(const FlowEvent *req, FlowEntry *flow, FlowEntry *rflow)
Definition: flow_table.cc:842
uint64_t total_alloc_
Definition: flow_table.h:118
int flow_logging_task_id() const
Definition: flow_table.h:256
FlowEntry * Find(const FlowKey &key)
Definition: flow_table.cc:136
void AddLinkLocalFlowInfo(int fd, uint32_t index, const FlowKey &key, const uint64_t timestamp)
Definition: flow_table.cc:753
void AddFlowInfo(FlowEntry *fe)
Definition: flow_table.cc:503
boost::intrusive::member_hook< FlowEntry, boost::intrusive::list_member_hook<>,&FlowEntry::free_list_node_ > Node
Definition: flow_table.h:100
boost::intrusive::list< FlowEntry, Node > FreeList
Definition: flow_table.h:101
void GrowFreeList()
Definition: flow_table.cc:960
LinkLocalFlowInfo(uint32_t index, const FlowKey &key, uint64_t t)
Definition: flow_table.h:167
Definition: agent.h:358
void DeleteVrf(VrfEntry *vrf)
friend class FetchFlowRecord
Definition: flow_table.h:265
std::pair< int, LinkLocalFlowInfo > LinkLocalFlowInfoPair
Definition: flow_table.h:171
void DisableKSyncSend(FlowEntry *flow, uint32_t evict_gen_id)
Definition: flow_table.cc:745
int flow_logging_task_id_
Definition: flow_table.h:308
uint32_t free_count() const
Definition: flow_table.h:110
FlowEntryFreeList(FlowTable *table)
Definition: flow_table.cc:965
FlowEntry * Allocate(const FlowKey &key)
Definition: flow_table.cc:1001
DISALLOW_COPY_AND_ASSIGN(FlowTable)
void Add(FlowEntry *flow, FlowEntry *rflow)
Definition: flow_table.cc:175
virtual ~FlowTable()
Definition: flow_table.cc:72
Agent * agent_
Definition: flow_table.h:293
virtual ~FlowTaskMsg()
Definition: flow_table.h:140
void ReleasePort(FlowEntry *flow, bool evict)
Definition: flow_table.cc:538
const LinkLocalFlowInfoMap & linklocal_flow_info_map()
Definition: flow_table.h:207
static void GetFlowSandeshActionParams(const FlowAction &action_info, std::string &action_str)
Definition: flow_table.cc:944
virtual ~FlowEntryFreeList()
Definition: flow_table.cc:979
std::map< int, LinkLocalFlowInfo > LinkLocalFlowInfoMap
Definition: flow_table.h:170
void Copy(FlowEntry *lhs, FlowEntry *rhs, bool update)
Definition: flow_table.cc:148
void InitDone()
Definition: flow_table.cc:86
DISALLOW_COPY_AND_ASSIGN(FlowEntryFreeList)
void RecomputeFlow(FlowEntry *flow)
Definition: flow_table.cc:519
bool DeleteFlows(FlowEntry *flow, FlowEntry *rflow)
Definition: flow_table.cc:342
static const uint32_t kInvalidFlowTableInstance
Definition: flow_table.h:155
size_t Size()
Definition: flow_table.h:199
FlowTaskMsg(FlowEntry *fe)
Definition: flow_table.h:139
void PopulateFlowEntriesUsingKey(const FlowKey &key, bool reverse_flow, FlowEntry **flow, FlowEntry **rflow)
Definition: flow_table.cc:368
void UpdateUnLocked(FlowEntry *flow, FlowEntry *rflow)
SandeshTraceBufferPtr FlowTraceBuf
uint32_t alloc_count() const
Definition: flow_table.h:111
void ProcessKSyncFlowEvent(const FlowEventKSync *req, FlowEntry *flow)
Definition: flow_table.cc:776
int flow_ksync_task_id_
Definition: flow_table.h:307
boost::intrusive::list_member_hook free_list_node_
Definition: flow_entry.h:843
uint32_t total_free() const
Definition: flow_table.h:113
FlowTable::FlowEntryMap::iterator begin()
Definition: flow_table.h:200
FlowTable * table_
Definition: flow_table.h:115
void Free(FlowEntry *flow)
Definition: flow_table.cc:1023
FlowTableKSyncObject * ksync_object_
Definition: flow_table.h:296
std::map< FlowKey, FlowEntry *, Inet4FlowKeyCmp > FlowEntryMap
Definition: flow_table.h:157
int flow_delete_task_id() const
Definition: flow_table.h:254
int flow_update_task_id_
Definition: flow_table.h:305
uint16_t table_index_
Definition: flow_table.h:295
void AddInternal(FlowEntry *flow, FlowEntry *new_flow, FlowEntry *rflow, FlowEntry *new_rflow, bool fwd_flow_update, bool rev_flow_update)
Definition: flow_table.cc:201
void SetAclFlowSandeshData(const AclDBEntry *acl, AclFlowResp &data, const int last_count)
uint32_t max_count_
Definition: flow_table.h:116
void EvictFlow(FlowEntry *flow, FlowEntry *rflow, uint32_t evict_gen_id)
Definition: flow_table.cc:547
Definition: acl.h:35
uint64_t total_free_
Definition: flow_table.h:119
FlowTable::FlowEntryMap::iterator end()
Definition: flow_table.h:203
FlowTableKSyncObject * ksync_object() const
Definition: flow_table.h:182
uint32_t max_count() const
Definition: flow_table.h:109
void DeleteMessage(FlowEntry *flow)
Definition: flow_table.cc:534
FlowEntryFreeList * free_list()
Definition: flow_table.h:239
Definition: acl.h:92
void DeleteFlowUveInfo(FlowEntry *fe)
Definition: flow_table.cc:496
void Init()
Definition: flow_table.cc:76
boost::intrusive_ptr< FlowEntry > FlowEntryPtr
Definition: flow_entry.h:125
void Update(FlowEntry *flow, FlowEntry *rflow)
Definition: flow_table.cc:184
friend void intrusive_ptr_release(FlowEntry *fe)
Definition: flow_entry.cc:570
void UpdateReverseFlow(FlowEntry *flow, FlowEntry *rflow)
Definition: flow_table.cc:447
static const uint32_t kGrowSize
Definition: flow_table.h:94