OpenSDN source code
flowtable_ksync.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  * Copyright Contributors to the OpenSDN project
4  */
5 
6 #ifndef __AGENT_FLOWTABLE_KSYNC_H__
7 #define __AGENT_FLOWTABLE_KSYNC_H__
8 
9 #include <boost/asio.hpp>
10 #include <boost/bind/bind.hpp>
11 
12 #include <db/db_entry.h>
13 #include <db/db_table.h>
14 #include <db/db_table_partition.h>
15 #include <ksync/ksync_index.h>
16 #include <ksync/ksync_entry.h>
17 #include <ksync/ksync_object.h>
18 #include <ksync/ksync_netlink.h>
19 #include <vrouter/ksync/agent_ksync_types.h>
21 #include <pkt/flow_proto.h>
22 #include <pkt/flow_table.h>
23 #include <vr_types.h>
24 #include <vr_flow.h>
25 
26 using namespace boost::placeholders;
27 
30 
33  uint32_t flow_handle_;
34  uint8_t gen_id_;
38 
39  void Reset() {
40  ksync_error_ = 0;
41  flow_handle_ = FlowEntry::kInvalidFlowHandle;
42  gen_id_ = 0;
43  evict_flow_bytes_ = 0;
44  evict_flow_packets_ = 0;
45  evict_flow_oflow_ = 0;
46  }
48  Reset();
49  }
50 };
51 
53 public:
56  uint32_t hash_id);
57  virtual ~FlowTableKSyncEntry();
58 
59  void Reset();
60  void Reset(FlowEntry *flow, uint32_t hash_id);
61 
62  FlowEntryPtr flow_entry() const {return flow_entry_;}
63  uint32_t hash_id() const {return hash_id_;}
64  void set_hash_id(uint32_t hash_id) {
65  hash_id_ = hash_id;
66  }
67  int Encode(sandesh_op::type op, char *buf, int buf_len);
68  KSyncObject *GetObject() const;
69 
70  std::string ToString() const;
71  bool IsLess(const KSyncEntry &rhs) const;
72  int AddMsg(char *buf, int buf_len);
73  int ChangeMsg(char *buf, int buf_len);
74  int DeleteMsg(char *buf, int buf_len);
75  void SetPcapData(FlowEntryPtr fe, std::vector<int8_t> &data);
76  // For flows allocate buffers in ksync-sock context
77  virtual bool pre_alloc_rx_buffer() const { return true; }
78  // KSync flow responses must be processed in multiple ksync response queues
79  // to support scaling. Distribute the flows based on flow-table index
80  virtual uint32_t GetTableIndex() const;
81  virtual bool Sync();
82  virtual KSyncEntry *UnresolvedReference();
83  virtual bool ShouldReEvalBackReference() const {
84  // no need to re-eval unresolved reference for flow entries, as they
85  // do not depend on anything
86  return false;
87  }
88  bool AllowDeleteStateComp() {return false;}
89  virtual void ErrorHandler(int, uint32_t, KSyncEvent) const;
90  virtual std::string VrouterError(uint32_t error) const;
91  uint8_t gen_id() { return gen_id_; }
92  void set_gen_id(uint8_t gen_id) { gen_id_ = gen_id; }
93  uint8_t evict_gen_id() { return evict_gen_id_; }
94  void set_evict_gen_id(uint8_t gen_id) { evict_gen_id_ = gen_id; }
95  uint8_t vrouter_gen_id() { return vrouter_gen_id_; }
96  uint32_t vrouter_hash_id() const { return vrouter_hash_id_; }
97  FlowEvent::Event last_event() const { return last_event_; }
98  void ReleaseToken();
100  ksync_response_info_.Reset();
101  }
102  void SetKSyncResponseInfo(int ksync_error, uint32_t flow_handle,
103  uint8_t gen_id, uint64_t evict_flow_bytes,
104  uint64_t evict_flow_packets,
105  int32_t evict_flow_oflow) {
106  ksync_response_info_.ksync_error_ = ksync_error;
107  ksync_response_info_.flow_handle_ = flow_handle;
108  ksync_response_info_.gen_id_ = gen_id;
109  ksync_response_info_.evict_flow_bytes_ = evict_flow_bytes;
110  ksync_response_info_.evict_flow_packets_ = evict_flow_packets;
111  ksync_response_info_.evict_flow_oflow_ = evict_flow_oflow;
112  }
114  return &ksync_response_info_;
115  }
116 
117  int ksync_response_error() const {
118  return ksync_response_info_.ksync_error_;
119  }
120 
122  return old_first_mirror_index_;
123  }
124  void set_transaction_id(uint32_t transaction_id) {
125  transaction_id_ = transaction_id;
126  }
127  uint32_t get_transaction_id() const { return transaction_id_;};
128 
129 private:
131  friend class KSyncFlowIndexManager;
132 
134  uint8_t gen_id_; // contains the last propagated genid from flow module
135  uint8_t evict_gen_id_; // contains current active gen-id in vrouter
136  uint8_t vrouter_gen_id_; // Used to identify the last genid sent to vrouter
137 
138  // used to identify last flow index sent to vrouter
139  // helps in knowing whether the vrouter response is index
140  // allocation or not
142 
143  uint32_t hash_id_;
145  uint32_t old_action_;
151  bool ecmp_;
153  uint32_t src_nh_id_;
155  boost::shared_ptr<Token> token_;
158  boost::intrusive::list_member_hook<> free_list_node_;
159  uint32_t qos_config_idx;
160  uint32_t transaction_id_;
163 };
164 
166 // Class to manage free-list of flow ksync entries
167 // Flow allocation can happen from multiple threads. In scaled scenarios
168 // allocation of flow-entries in multi-thread environment adds overheads.
169 // The KSyncFlowEntryFreeList helps to maintain a per task free-list. Alloc/Free
170 // can happen without lock.
171 //
172 // Alloc and Free happens in a chunk. Alloc/Free are done based on thresholds
173 // in task context of the corresponding flow-table
176 public:
177  static const uint32_t kInitCount = (25 * 1000);
178  static const uint32_t kTestInitCount = (5 * 1000);
179  static const uint32_t kGrowSize = (1 * 1000);
180  static const uint32_t kMinThreshold = (4 * 1000);
181  static const uint32_t kMaxThreshold = (100 * 1000);
182 
183  typedef boost::intrusive::member_hook<FlowTableKSyncEntry,
184  boost::intrusive::list_member_hook<>,
186  typedef boost::intrusive::list<FlowTableKSyncEntry, Node> FreeList;
187 
190  uint32_t hash_id);
191  virtual ~KSyncFlowEntryFreeList();
192 
193  void Reset();
194  void Reset(FlowEntryPtr fe, uint32_t hash_id);
195 
196  FlowTableKSyncEntry *Allocate(const KSyncEntry *key);
197  void Free(FlowTableKSyncEntry *flow);
198  void Grow();
199  uint32_t max_count() const { return max_count_; }
200  uint32_t free_count() const { return free_list_.size(); }
201  uint32_t alloc_count() const { return (max_count_ - free_list_.size()); }
202  uint32_t total_alloc() const { return total_alloc_; }
203  uint32_t total_free() const { return total_free_; }
204 
205 private:
207  uint32_t max_count_;
209  uint64_t total_alloc_;
210  uint64_t total_free_;
213 };
214 
216 public:
217  // flow dependency timer on mirror entry in msec
218  static const uint32_t kFlowDepSyncTimeout = 1000;
219  static const uint32_t KFlowUnresolvedListYield = 32;
220  FlowTableKSyncObject(KSync *ksync);
221  FlowTableKSyncObject(KSync *ksync, int max_index);
222  virtual ~FlowTableKSyncObject();
223 
224  void Init();
225  void Shutdown() { }
226 
227  KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index);
228  void Free(KSyncEntry *key);
229  bool DoEventTrace(void) { return false; }
230  FlowTableKSyncEntry *Find(FlowEntry *key);
231 
232  vr_flow_req &flow_req() { return flow_req_; }
233  KSync *ksync() const { return ksync_; }
234  void set_flow_table(FlowTable *table) { flow_table_ = table; }
235  FlowTable *flow_table() const { return flow_table_; }
236  void UpdateFlowHandle(FlowTableKSyncEntry *entry, uint32_t flow_handle);
237  void UpdateKey(KSyncEntry *entry, uint32_t flow_handle);
238  uint32_t GetKey(KSyncEntry *entry);
239 
240  void GrowFreeList();
241  KSyncFlowEntryFreeList *free_list() { return &free_list_; }
242 
243  void NetlinkAck(KSyncEntry *entry, KSyncEntry::KSyncEvent event);
244  void GenerateKSyncEvent(FlowTableKSyncEntry *entry,
245  KSyncEntry::KSyncEvent event);
246  void StartTimer();
247  bool TimerExpiry();
248  void UpdateUnresolvedFlowEntry(FlowEntryPtr flowptr);
249 private:
250  friend class KSyncSandeshContext;
251  friend class FlowTable;
254  vr_flow_req flow_req_;
256  std::list<FlowEntryPtr> unresolved_flow_list_;
259 };
260 
261 #endif /* __AGENT_FLOWTABLE_KSYNC_H__ */
static bool IsLess(const ShowRoute &lhs, const ShowRoute &rhs, const BgpSandeshContext *bsc, const string &table_name)
static const uint32_t kInvalidFlowHandle
Definition: flow_entry.h:522
uint32_t get_transaction_id() const
FlowKSyncResponseInfo ksync_response_info_
boost::intrusive::list_member_hook free_list_node_
int ksync_response_error() const
void set_evict_gen_id(uint8_t gen_id)
void set_gen_id(uint8_t gen_id)
FlowTableKSyncObject * ksync_obj_
virtual bool ShouldReEvalBackReference() const
void SetKSyncResponseInfo(int ksync_error, uint32_t flow_handle, uint8_t gen_id, uint64_t evict_flow_bytes, uint64_t evict_flow_packets, int32_t evict_flow_oflow)
uint32_t old_component_nh_idx_
const FlowKSyncResponseInfo * ksync_response_info() const
FlowEntryPtr flow_entry_
FlowEvent::Event last_event() const
uint32_t old_first_mirror_index_
FlowEntryPtr flow_entry() const
void set_hash_id(uint32_t hash_id)
uint32_t old_second_mirror_index_
uint32_t vrouter_hash_id() const
DISALLOW_COPY_AND_ASSIGN(FlowTableKSyncEntry)
boost::shared_ptr< Token > token_
FlowEvent::Event last_event_
uint32_t old_first_mirror_index()
uint32_t hash_id() const
virtual bool pre_alloc_rx_buffer() const
void set_transaction_id(uint32_t transaction_id)
KSync * ksync() const
DISALLOW_COPY_AND_ASSIGN(FlowTableKSyncObject)
KSyncFlowEntryFreeList free_list_
std::list< FlowEntryPtr > unresolved_flow_list_
void set_flow_table(FlowTable *table)
FlowTable * flow_table() const
vr_flow_req & flow_req()
KSyncFlowEntryFreeList * free_list()
boost::intrusive::member_hook< FlowTableKSyncEntry, boost::intrusive::list_member_hook<>, &FlowTableKSyncEntry::free_list_node_ > Node
uint32_t max_count() const
uint32_t alloc_count() const
KSyncFlowEntryFreeList(FlowTableKSyncObject *object, FlowEntry *flow, uint32_t hash_id)
FlowTableKSyncObject * object_
uint32_t free_count() const
boost::intrusive::list< FlowTableKSyncEntry, Node > FreeList
uint32_t total_alloc() const
DISALLOW_COPY_AND_ASSIGN(KSyncFlowEntryFreeList)
void Reset(FlowEntryPtr fe, uint32_t hash_id)
uint32_t total_free() const
Definition: timer.h:58
boost::intrusive_ptr< FlowEntry > FlowEntryPtr
Definition: flow_entry.h:126
uint8_t type
Definition: load_balance.h:2
static string ToString(PhysicalDevice::ManagementProtocol proto)
int hash_id