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