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