OpenSDN source code
flow_stats_collector.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #ifndef vnsw_agent_flow_stats_collector_h
6 #define vnsw_agent_flow_stats_collector_h
7 
8 #include <atomic>
9 
10 #include <boost/static_assert.hpp>
11 #include <pkt/flow_table.h>
12 #include <cmn/agent_cmn.h>
13 #include <cmn/index_vector.h>
14 #include <uve/stats_collector.h>
17 #include <sandesh/common/flow_types.h>
21 
22 // Forward declaration
23 class AgentUtXmlFlowThreshold;
24 class AgentUtXmlFlowThresholdValidate;
25 class FlowStatsRecordsReq;
26 class FetchFlowStatsRecord;
27 class FlowStatsManager;
28 
29 struct KFlowData {
30 public:
32  uint16_t tcp_flags;
33  uint16_t flags;
34 };
35 
36 //Defines the functionality to periodically read flow stats from
37 //shared memory (between agent and Kernel) and export this stats info to
38 //collector. Also responsible for aging of flow entries. Runs in the context
39 //of kTaskFlowStatsCollector which has exclusion with "db::DBTable",
40 //
41 // The algorithm for ageing flows,
42 // - The complete flow-table will be scanned every 25% of ageing time
43 // - An implication of this is, flow ageing will have accuracy of 25%
44 // - Run timer every kFlowStatsTimerInterval msec (100 msec)
45 // - Compute number of flow-entres to visit in kFlowStatsTimerInterval
46 // - This is subject to constraing that complete flow table must be scanned
47 // in 25% of ageing time
48 // - On every timer expiry accumulate the number of entries to visit into
49 // entries_to_visit_ variable
50 // - Start a task (Flow AgeingTask) to scan the flow-entries
51 // - On every run of task, visit upto kFlowsPerTask entries
52 // If scan is not complete, continue the task
53 // On completion of scan, stop the task
54 //
55 // On every visit of flow, check if flow is idle for configured ageing time and
56 // delete the idle flows
57 //
58 // The flow_tree_ maintains flows sorted on flow pointer. This tree cannot be
59 // used to scan flows for ageing since entries can be added/deleted between
60 // ageing tasks. Alternatively, another list is maintained in the sequence
61 // flows are added to flow ageing module.
63 public:
64  // Default ageing time
65  static const uint64_t FlowAgeTime = 1000000 * 180;
66  // Default TCP ageing time
67  static const uint64_t FlowTcpSynAgeTime = 1000000 * 180;
68 
69  // Time within which complete table must be scanned
70  // Specified in terms of percentage of aging-time
71  static const uint32_t kFlowScanTime = 25;
72  // Flog ageing timer interval in milliseconds
73  static const uint32_t kFlowStatsTimerInterval = 100;
74  // Minimum flows to visit per interval
75  static const uint32_t kMinFlowsPerTimer = 3000;
76  // Number of flows to visit per task
77  static const uint32_t kFlowsPerTask = 256;
78 
79  // Retry flow-delete after 5 second
80  static const uint64_t kFlowDeleteRetryTime = (5 * 1000 * 1000);
81 
82  static const uint32_t kDefaultFlowSamplingThreshold = 500;
83  static const uint8_t kMaxFlowMsgsPerSend = 16;
84 
85  typedef std::map<const FlowEntry*, FlowExportInfo> FlowEntryTree;
87 
88  // Task in which the actual flow table scan happens. See description above
89  class AgeingTask : public Task {
90  public:
92  virtual ~AgeingTask();
93  bool Run();
94  std::string Description() const;
95  private:
97  };
98 
99  FlowStatsCollector(boost::asio::io_context &io, int intvl,
100  uint32_t flow_cache_timeout,
101  AgentUveBase *uve, uint32_t instance_id,
102  FlowAgingTableKey *key,
103  FlowStatsManager *aging_module,
105  virtual ~FlowStatsCollector();
106 
108  void set_flow_age_time_intvl(uint64_t interval) {
109  flow_age_time_intvl_ = interval;
110  }
111 
112  uint32_t flow_age_time_intvl_in_secs() const {
113  return flow_age_time_intvl_/(1000 * 1000);
114  }
115  uint64_t flow_tcp_syn_age_time() const {
116  return flow_tcp_syn_age_time_;
117  }
118  void set_flow_tcp_syn_age_time(uint64_t interval) {
119  flow_tcp_syn_age_time_ = interval;
120  }
122  bool Run();
123  bool RunAgeingTask();
124  uint32_t ProcessFlow(FlowExportInfoList::iterator &it,
125  KSyncFlowMemory *ksync_obj,
126  FlowExportInfo *info, uint64_t curr_time);
127  bool AgeFlow(KSyncFlowMemory *ksync_obj, const vr_flow_entry *k_flow,
128  const vr_flow_stats &k_stats, const KFlowData &kinfo,
129  FlowExportInfo *info, uint64_t curr_time);
130  bool EvictFlow(KSyncFlowMemory *ksync_obj, const vr_flow_entry *k_flow,
131  uint16_t k_flow_flags, uint32_t flow_handle, uint16_t gen_id,
132  FlowExportInfo *info, uint64_t curr_time);
133  uint32_t RunAgeing(uint32_t max_count);
134  void UpdateFlowAgeTime(uint64_t usecs) {
135  flow_age_time_intvl_ = usecs;
136  }
137  void UpdateFlowAgeTimeInSecs(uint32_t secs) {
138  UpdateFlowAgeTime(secs * 1000 * 1000);
139  }
140 
141  void UpdateFloatingIpStats(const FlowExportInfo *flow, uint64_t bytes,
142  uint64_t pkts);
143  void UpdateStatsEvent(const FlowEntryPtr &flow, uint32_t bytes,
144  uint32_t packets, uint32_t oflow_bytes,
145  const boost::uuids::uuid &u);
146  void Shutdown();
147  void AddEvent(const FlowEntryPtr &flow);
148  void DeleteEvent(const FlowEntryPtr &flow, const RevFlowDepParams &params);
149 
150  bool FindFlowExportInfo(const FlowEntry *fe, FlowEntryTree::iterator &it);
152  const FlowExportInfo *FindFlowExportInfo(const FlowEntry *fe) const;
153  static uint64_t GetFlowStats(const uint16_t &oflow_data, const uint32_t &data);
154  size_t Size() const { return flow_tree_.size(); }
155  size_t AgeTreeSize() const { return flow_export_info_list_.size(); }
156  void NewFlow(FlowEntry *flow);
157  void set_deleted(bool val) {
158  deleted_ = val;
159  }
160  bool deleted() const {
161  return deleted_;
162  }
164  return flow_aging_key_;
165  }
166  int task_id() const { return task_id_; }
167  uint32_t instance_id() const { return instance_id_; }
168  const Queue *queue() const { return &request_queue_; }
171  friend class FlowStatsRecordsReq;
172  friend class FetchFlowStatsRecord;
173  friend class FlowStatsManager;
175 
176 private:
177  static uint64_t GetCurrentTime();
178  uint32_t TimersPerScan();
179  void UpdateEntriesToVisit();
180  void EvictedFlowStatsUpdate(const FlowEntryPtr &flow, uint32_t bytes,
181  uint32_t packets, uint32_t oflow_bytes,
182  const boost::uuids::uuid &u);
183  void UpdateFlowStats(FlowExportInfo *info, uint64_t teardown_time);
185  uint32_t bytes,
186  uint16_t oflow_bytes,
187  uint32_t pkts,
188  uint16_t oflow_pkts,
189  uint64_t time,
190  bool teardown_time);
192  uint32_t bytes,
193  uint16_t oflow_bytes,
194  uint32_t pkts,
195  uint16_t oflow_pkts,
196  uint64_t time,
197  bool teardown_time);
198  void FlowDeleteEnqueue(FlowExportInfo *info, uint64_t t);
199  void FlowEvictEnqueue(FlowExportInfo *info, uint64_t t,
200  uint32_t flow_handle, uint16_t gen_id);
201  void UpdateThreshold(uint32_t new_value);
202 
204  uint64_t bytes, uint64_t pkts);
206  uint64_t bytes, uint64_t pkts);
207  bool ShouldBeAged(FlowExportInfo *info, const vr_flow_entry *k_flow,
208  const vr_flow_stats &k_stats, uint64_t curr_time);
209  uint64_t GetUpdatedFlowPackets(const FlowExportInfo *stats,
210  uint64_t k_flow_pkts);
211  uint64_t GetUpdatedFlowBytes(const FlowExportInfo *stats,
212  uint64_t k_flow_bytes);
214  (const FlowExportInfo *flow);
215  uint32_t ReverseFlowFip(const FlowExportInfo *info);
217  bool RequestHandler(boost::shared_ptr<FlowExportReq> req);
218  bool RequestHandlerEntry();
219  void RequestHandlerExit(bool done);
220  void AddFlow(FlowExportInfo info);
221  void DeleteFlow(FlowEntryTree::iterator &it);
222  void UpdateFlowIterationKey(const FlowEntry *del_flow,
223  FlowEntryTree::iterator &tree_it);
224  void HandleFlowStatsUpdate(const FlowKey &key, uint32_t bytes,
225  uint32_t packets, uint32_t oflow_bytes);
226 
228  int task_id_;
229  boost::uuids::random_generator rand_gen_;
232  // Number of entries pending to be visited
235 
238  // Flag to specify if flow-delete request event must be retried
239  // If enabled
240  // Dont remove FlowExportInfo from list after generating delete event
241  // Retry delete event after kFlowDeleteRetryTime
242  // Else
243  // Remove FlowExportInfo from list after generating delete event
244  // FIXME : disabling is only a debug feature for now. Once we remove
245  // from list, flow will never be aged. So, need to ensure all scenarios
246  // are covered before disabling the fag
249  std::atomic<bool> deleted_;
251  uint32_t instance_id_;
255  // Number of timer fires needed to scan the flow-table once
256  // This is based on ageing timer
258  // Cached UTC Time stamp
259  // The timestamp is taken once on FlowStatsCollector::RequestHandlerEntry()
260  // and used for all requests in current run
261  uint64_t current_time_;
263 
264  // Per ageing-timer stats for debugging
265  uint32_t flows_visited_;
266  uint32_t flows_aged_;
267  uint32_t flows_evicted_;
269 };
270 
272 public:
273  static const int kMaxCollectors = 2;
274  typedef boost::shared_ptr<FlowStatsCollector> FlowStatsCollectorPtr;
276  FlowStatsManager *mgr);
277  FlowStatsCollector* GetCollector(uint8_t idx) const;
278  void SetExpiryTime(int time);
279  int GetExpiryTime() const;
280  void MarkDelete();
281  void ClearDelete();
282  bool IsDeleted() const;
283  void SetFlowAgeTime(uint64_t value);
284  uint64_t GetFlowAgeTime() const;
285  bool CanDelete() const;
286  void Shutdown();
288  void UpdateAgeTimeInSeconds(uint32_t age_time);
289  uint32_t GetAgeTimeInSeconds() const;
290  size_t Size() const;
291 private:
294 };
295 
296 #endif //vnsw_agent_flow_stats_collector_h
Definition: agent.h:360
FlowStatsCollector * GetCollector(uint8_t idx) const
FlowStatsCollectorObject(Agent *agent, FlowStatsCollectorReq *req, FlowStatsManager *mgr)
FlowStatsCollectorPtr collectors[kMaxCollectors]
void UpdateAgeTimeInSeconds(uint32_t age_time)
boost::shared_ptr< FlowStatsCollector > FlowStatsCollectorPtr
DISALLOW_COPY_AND_ASSIGN(FlowStatsCollectorObject)
void SetFlowAgeTime(uint64_t value)
FlowStatsCollector * FlowToCollector(const FlowEntry *flow)
bool Run()
Code to execute in a task. Returns true if task is completed. Return false to reschedule the task.
std::string Description() const
Gives a description of the task.
AgeingTask(FlowStatsCollector *fsc)
FlowExportInfoList flow_export_info_list_
void AddFlow(FlowExportInfo info)
void UpdateFlowStats(FlowExportInfo *info, uint64_t teardown_time)
bool ShouldBeAged(FlowExportInfo *info, const vr_flow_entry *k_flow, const vr_flow_stats &k_stats, uint64_t curr_time)
FlowStatsCollectorObject * parent_
void EvictedFlowStatsUpdate(const FlowEntryPtr &flow, uint32_t bytes, uint32_t packets, uint32_t oflow_bytes, const boost::uuids::uuid &u)
friend class FetchFlowStatsRecord
uint32_t flow_age_time_intvl_in_secs() const
FlowStatsManager * flow_stats_manager_
void set_flow_age_time_intvl(uint64_t interval)
void UpdateFlowIterationKey(const FlowEntry *del_flow, FlowEntryTree::iterator &tree_it)
const Queue * queue() const
void UpdateFlowStatsInternal(FlowExportInfo *info, uint32_t bytes, uint16_t oflow_bytes, uint32_t pkts, uint16_t oflow_pkts, uint64_t time, bool teardown_time)
friend class FlowStatsRecordsReq
void HandleFlowStatsUpdate(const FlowKey &key, uint32_t bytes, uint32_t packets, uint32_t oflow_bytes)
void set_flow_tcp_syn_age_time(uint64_t interval)
void UpdateFloatingIpStats(const FlowExportInfo *flow, uint64_t bytes, uint64_t pkts)
void FlowDeleteEnqueue(FlowExportInfo *info, uint64_t t)
void FlowEvictEnqueue(FlowExportInfo *info, uint64_t t, uint32_t flow_handle, uint16_t gen_id)
DISALLOW_COPY_AND_ASSIGN(FlowStatsCollector)
static const uint64_t kFlowDeleteRetryTime
static const uint32_t kFlowStatsTimerInterval
static const uint32_t kFlowScanTime
friend class AgentUtXmlFlowThresholdValidate
WorkQueue< boost::shared_ptr< FlowExportReq > > Queue
void UpdateThreshold(uint32_t new_value)
void AddEvent(const FlowEntryPtr &flow)
uint32_t RunAgeing(uint32_t max_count)
uint64_t GetUpdatedFlowBytes(const FlowExportInfo *stats, uint64_t k_flow_bytes)
void UpdateVmiTagBasedStats(FlowExportInfo *info, uint64_t bytes, uint64_t pkts)
InterfaceUveTable::FloatingIp * ReverseFlowFipEntry(const FlowExportInfo *flow)
bool EvictFlow(KSyncFlowMemory *ksync_obj, const vr_flow_entry *k_flow, uint16_t k_flow_flags, uint32_t flow_handle, uint16_t gen_id, FlowExportInfo *info, uint64_t curr_time)
static const uint32_t kMinFlowsPerTimer
static const uint32_t kDefaultFlowSamplingThreshold
static const uint64_t FlowTcpSynAgeTime
static uint64_t GetCurrentTime()
void UpdateStatsEvent(const FlowEntryPtr &flow, uint32_t bytes, uint32_t packets, uint32_t oflow_bytes, const boost::uuids::uuid &u)
void UpdateFlowAgeTime(uint64_t usecs)
void set_deleted(bool val)
size_t AgeTreeSize() const
void DeleteEvent(const FlowEntryPtr &flow, const RevFlowDepParams &params)
void RequestHandlerExit(bool done)
uint64_t flow_tcp_syn_age_time() const
uint64_t GetUpdatedFlowPackets(const FlowExportInfo *stats, uint64_t k_flow_pkts)
void UpdateFlowAgeTimeInSecs(uint32_t secs)
bool FindFlowExportInfo(const FlowEntry *fe, FlowEntryTree::iterator &it)
boost::uuids::uuid rand_gen()
friend class AgentUtXmlFlowThreshold
std::atomic< bool > deleted_
uint32_t instance_id() const
uint32_t ProcessFlow(FlowExportInfoList::iterator &it, KSyncFlowMemory *ksync_obj, FlowExportInfo *info, uint64_t curr_time)
static const uint64_t FlowAgeTime
static const uint8_t kMaxFlowMsgsPerSend
bool RequestHandler(boost::shared_ptr< FlowExportReq > req)
std::map< const FlowEntry *, FlowExportInfo > FlowEntryTree
VmInterfaceKey ReverseFlowFipVmi(const FlowExportInfo *info)
void DeleteFlow(FlowEntryTree::iterator &it)
const FlowEntry * flow_iteration_key_
const FlowAgingTableKey & flow_aging_key() const
void NewFlow(FlowEntry *flow)
static const uint32_t kFlowsPerTask
void UpdateInterVnStats(FlowExportInfo *info, uint64_t bytes, uint64_t pkts)
static uint64_t GetFlowStats(const uint16_t &oflow_data, const uint32_t &data)
uint32_t ReverseFlowFip(const FlowExportInfo *info)
FlowAgingTableKey flow_aging_key_
void UpdateFlowStatsInternalLocked(FlowExportInfo *info, uint32_t bytes, uint16_t oflow_bytes, uint32_t pkts, uint16_t oflow_pkts, uint64_t time, bool teardown_time)
boost::uuids::random_generator rand_gen_
bool AgeFlow(KSyncFlowMemory *ksync_obj, const vr_flow_entry *k_flow, const vr_flow_stats &k_stats, const KFlowData &kinfo, FlowExportInfo *info, uint64_t curr_time)
Task is a class to describe a computational task within OpenSDN control plane applications....
Definition: task.h:79
boost::intrusive_ptr< FlowEntry > FlowEntryPtr
Definition: flow_entry.h:125
boost::intrusive::list< FlowExportInfo > FlowExportInfoList
Definition: io_utils.cc:11
uint16_t tcp_flags
uint16_t underlay_src_port
boost::uuids::uuid uuid