OpenSDN source code
flow_mgmt_entry.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved.
3  * Copyright Contributors to the OpenSDN project
4  */
5 
7 #include <pkt/flow_event.h>
9 #include <pkt/flow_mgmt.h>
10 
12  if (node) {
13  flow_list_.push_back(*node);
14  return true;
15  }
16  return false;
17 }
18 
20  flow_list_.erase(flow_list_.iterator_to(*node));
21  return flow_list_.size();
22 }
23 
24 // An entry *cannot* be deleted if
25 // - It contains flows
26 // - It has seen ADD but not seen any DELETE
28  assert(oper_state_ != INVALID);
29  if (flow_list_.size())
30  return false;
31 
32  return (oper_state_ != OPER_ADD_SEEN);
33 }
34 
35 // Handle Add/Change event for DBEntry
37  const FlowMgmtRequest *req, FlowMgmtKey *key) {
39  FlowEvent::Event event = req->GetResponseEvent();
40  if (event == FlowEvent::INVALID)
41  return false;
42 
43  FlowList::iterator it = flow_list_.begin();
44  while (it != flow_list_.end()) {
45  FlowMgmtKeyNode *node = &(*it);
46  mgr->DBEntryEvent(event, key, node->flow_entry());
47  it++;
48  }
49 
50  return true;
51 }
52 
54  const FlowMgmtRequest *req,
55  FlowMgmtKey *key) {
56  return OperEntryAdd(mgr, req, key);
57 }
58 
59 // Handle Delete event for DBEntry
61  const FlowMgmtRequest *req,
62  FlowMgmtKey *key) {
64  //If the delete is implicit there is no DB entry
65  //and hence no free notify should be sent, hence
66  //dont update the state to DEL SEEN
68  gen_id_ = req->gen_id();
69  }
70 
71  FlowEvent::Event event = req->GetResponseEvent();
72  if (event == FlowEvent::INVALID)
73  return false;
74 
75  FlowList::iterator it = flow_list_.begin();
76  while (it != flow_list_.end()) {
77  FlowMgmtKeyNode *node = &(*it);
78  mgr->DBEntryEvent(event, key, node->flow_entry());
79  it++;
80  }
81 
82  return true;
83 }
84 
86  const int last_count) const {
87  string uuid_str = UuidToString(acl->GetUuid());
88  std::stringstream ss;
89  ss << uuid_str << ":";
90  ss << last_count;
91  return ss.str();
92 }
93 
95  const std::string &ace_id) {
96  string uuid_str = UuidToString(acl->GetUuid());
97  std::stringstream ss;
98  ss << uuid_str << ":";
99  ss << ace_id;
100  return ss.str();
101 }
102 
104  AclFlowCountResp &data,
105  const std::string& ace_id) {
106  int count = 0;
107  bool key_set = false;
108  AceIdFlowCntMap::iterator aceid_it = aceid_cnt_map_.upper_bound(ace_id);
109  std::vector<AceIdFlowCnt> id_cnt_l;
110  while (aceid_it != aceid_cnt_map_.end()) {
111  AceIdFlowCnt id_cnt_s;
112  id_cnt_s.ace_id = aceid_it->first;
113  id_cnt_s.flow_cnt = aceid_it->second;
114  id_cnt_l.push_back(id_cnt_s);
115  count++;
116  ++aceid_it;
117  if (count == MaxResponses && aceid_it != aceid_cnt_map_.end()) {
118  data.set_iteration_key(GetAceSandeshDataKey(acl, id_cnt_s.ace_id));
119  key_set = true;
120  break;
121  }
122  }
123  data.set_aceid_cnt_list(id_cnt_l);
124 
125  data.set_flow_count(Size());
126  data.set_flow_miss(flow_miss_);
127 
128  if (!key_set) {
129  data.set_iteration_key(GetAceSandeshDataKey(acl, Agent::NullString()));
130  }
131 }
132 
134  AclFlowResp &data,
135  const int last_count,
136  Agent *agent) {
137  int count = 0;
138  bool key_set = false;
139  FlowList::iterator fe_tree_it = flow_list_.begin();
140  while (fe_tree_it != flow_list_.end() && (count + 1) < last_count) {
141  fe_tree_it++;
142  count++;
143  }
144  data.set_flow_count(Size());
145  data.set_flow_miss(flow_miss_);
146  std::vector<FlowSandeshData> flow_entries_l;
147  while(fe_tree_it != flow_list_.end()) {
148  FlowMgmtKeyNode *node = &(*fe_tree_it);
149  const FlowEntry *fe = node->flow_entry();
150  FlowSandeshData fe_sandesh_data;
151  fe->SetAclFlowSandeshData(acl, fe_sandesh_data, agent);
152 
153  flow_entries_l.push_back(fe_sandesh_data);
154  count++;
155  ++fe_tree_it;
156  if (count == (MaxResponses + last_count) &&
157  fe_tree_it != flow_list_.end()) {
158  data.set_iteration_key(GetAclFlowSandeshDataKey(acl, count));
159  key_set = true;
160  break;
161  }
162  }
163  data.set_flow_entries(flow_entries_l);
164  if (!key_set) {
165  data.set_iteration_key(GetAclFlowSandeshDataKey(acl, 0));
166  }
167 }
168 
170  AclEntryIDList::const_iterator id_it;
171  for (id_it = id_list->begin(); id_it != id_list->end(); ++id_it) {
172  aceid_cnt_map_[id_it->id_] -= 1;
173  }
174 }
175 
176 bool AclFlowMgmtEntry::Add(const AclEntryIDList *id_list, FlowEntry *flow,
177  const AclEntryIDList *old_id_list,
178  FlowMgmtKeyNode *node) {
179  if (old_id_list) {
180  DecrementAceIdCountMap(old_id_list);
181  }
182  if (id_list->size()) {
183  AclEntryIDList::const_iterator id_it;
184  for (id_it = id_list->begin(); id_it != id_list->end(); ++id_it) {
185  aceid_cnt_map_[id_it->id_] += 1;
186  }
187  } else {
188  flow_miss_++;
189  }
190  return FlowMgmtEntry::Add(flow, node);
191 }
192 
194  FlowMgmtKeyNode *node) {
195  if (id_list->size()) {
196  DecrementAceIdCountMap(id_list);
197  }
198  return FlowMgmtEntry::Delete(flow, node);
199 }
200 
202  const FlowMgmtRequest *req,
203  FlowMgmtKey *key) {
205  gen_id_ = req->gen_id();
206  FlowEvent::Event event = req->GetResponseEvent();
207  if (event == FlowEvent::INVALID)
208  return false;
209 
210  FlowList::iterator it = flow_list_.begin();
211  while (it != flow_list_.end()) {
212  FlowMgmtKeyNode *node = &(*it);
213  mgr->NonOperEntryEvent(event, node->flow_entry());
214  it++;
215  }
216  return true;
217 }
218 
219 // Update health check on all the BgpAsAService flows
221  Agent *agent, FlowMgmtManager *mgr,
224  for (FlowList::iterator it = flow_list_.begin();
225  it != flow_list_.end(); ++it) {
226  FlowMgmtKeyNode *node = &(*it);
228  mgr->FindBgpAsAServiceInfo(node->flow_entry(), key);
229  if (bkey == NULL)
230  continue;
231 
233  bkey->StartHealthCheck(agent, node->flow_entry(),
234  req->health_check_uuid());
235  else
236  bkey->StopHealthCheck(node->flow_entry());
237  }
238  return true;
239 }
240 
242  bool local_flow, bool old_ingress) {
243  if (add_flow) {
244  if (flow->is_flags_set(FlowEntry::LocalFlow)) {
247  } else if (flow->is_flags_set(FlowEntry::IngressDir)) {
249  } else {
251  }
252 
253  return;
254  }
255 
256  if (local_flow)
257  return;
258 
259  bool new_ingress = flow->is_flags_set(FlowEntry::IngressDir);
260  if (new_ingress != old_ingress) {
261  if (new_ingress) {
264  } else {
267  }
268  }
269 }
270 
271 void VnFlowMgmtEntry::UpdateCounterOnDel(FlowEntry *flow, bool local_flow,
272  bool old_ingress) {
273  if (local_flow) {
276  return;
277  }
278 
279  if (old_ingress) {
281  } else {
283  }
284 }
285 
287  bool added = FlowMgmtEntry::Add(flow, node);
288  if (added) {
289  flow_created_++;
290  }
291  return added;
292 }
293 
295  flow_aged_++;
296  return FlowMgmtEntry::Delete(flow, node);
297 }
298 
300 (FlowMgmtManager *mgr, InetRouteFlowMgmtKey *covering_route,
301  InetRouteFlowMgmtKey *key){
302  FlowList::iterator it = flow_list_.begin();
303  while (it != flow_list_.end()) {
304  FlowMgmtKeyNode *node = &(*it);
305  // Queue the DB Event only route key matches src or dst ip matches.
306  if (key->NeedsReCompute(node->flow_entry())) {
307  mgr->DBEntryEvent(FlowEvent::RECOMPUTE_FLOW, covering_route,
308  node->flow_entry());
309  }
310  it++;
311  }
312 
313  return true;
314 }
315 
317  const FlowMgmtRequest *req,
318  FlowMgmtKey *key) {
319  assert(req->event() == FlowMgmtRequest::DELETE_LAYER2_FLOW);
320 
321  FlowList::iterator it = flow_list_.begin();
322  while (it != flow_list_.end()) {
323  FlowEvent::Event event;
324  FlowMgmtKeyNode *node = &(*it);
325  it++;
326  FlowEntry *fe = node->flow_entry();
327  if (fe->l3_flow()) {
329  } else {
330  event = FlowEvent::DELETE_FLOW;
331  }
332 
333  mgr->DBEntryEvent(event, key, fe);
334  }
335 
336  return true;
337 }
338 
340  const VrfEntry *vrf) :
341  vrf_(vrf), vrf_id_(vrf->vrf_id()),
342  inet4_(this, vrf, vrf->GetRouteTable(Agent::INET4_UNICAST)),
343  inet6_(this, vrf, vrf->GetRouteTable(Agent::INET6_UNICAST)),
344  bridge_(this, vrf, vrf->GetRouteTable(Agent::BRIDGE)),
345  vrf_tree_(vrf_tree) {
346 }
347 
349  if (FlowMgmtEntry::CanDelete() == false)
350  return false;
351 
352  if (inet4_.deleted() == false || inet6_.deleted() == false ||
353  bridge_.deleted() == false) {
354  return false;
355  }
356 
357  return (vrf_tree_->mgr()->HasVrfFlows(vrf_id_) == false);
358 }
359 
361  const VrfEntry *vrf, AgentRouteTable *table) :
362  deleted_(false), table_ref_(this, NULL),
363  vrf_mgmt_entry_(vrf_mgmt_entry), vrf_(vrf) {
364  if (vrf->IsDeleted() == false) {
365  table_ref_.Reset(table->deleter());
366  } else {
367  deleted_ = true;
368  }
369 }
370 
372  table_ref_.Reset(NULL);
373 }
374 
376  deleted_ = true;
377  vrf_mgmt_entry_->vrf_tree()->mgr()->RetryVrfDeleteEvent(vrf_);
378 }
std::vector< AclEntryID > AclEntryIDList
Definition: acl_entry.h:86
Definition: acl.h:92
const boost::uuids::uuid & GetUuid() const
Definition: acl.h:112
void FillAclFlowSandeshInfo(const AclDBEntry *acl, AclFlowResp &data, const int last_count, Agent *agent)
AceIdFlowCntMap aceid_cnt_map_
std::string GetAclFlowSandeshDataKey(const AclDBEntry *acl, const int last_count) const
std::string GetAceSandeshDataKey(const AclDBEntry *acl, const std::string &ace_id)
bool Add(const AclEntryIDList *ace_id_list, FlowEntry *flow, const AclEntryIDList *old_id_list, FlowMgmtKeyNode *node)
void FillAceFlowSandeshInfo(const AclDBEntry *acl, AclFlowCountResp &data, const std::string &ace_id)
void DecrementAceIdCountMap(const AclEntryIDList *id_list)
bool Delete(const AclEntryIDList *ace_id_list, FlowEntry *flow, FlowMgmtKeyNode *node)
Agent supports multiple route tables - Inet-unicast (IPv4/IPv6), Inet-multicast, bridge,...
Definition: agent_route.h:110
LifetimeActor * deleter()
Definition: agent_route.cc:452
Definition: agent.h:361
static const std::string & NullString()
Definition: agent.h:440
virtual bool HealthCheckUpdate(Agent *agent, FlowMgmtManager *mgr, BgpAsAServiceFlowMgmtKey &key, BgpAsAServiceFlowMgmtRequest *req)
virtual bool NonOperEntryDelete(FlowMgmtManager *mgr, const FlowMgmtRequest *req, FlowMgmtKey *key)
void StartHealthCheck(Agent *agent, FlowEntry *flow, const boost::uuids::uuid &hc_uuid)
void StopHealthCheck(FlowEntry *flow)
BgpAsAServiceFlowMgmtRequest::Type type() const
const boost::uuids::uuid & health_check_uuid() const
bool IsDeleted() const
Definition: db_entry.h:49
void SetAclFlowSandeshData(const AclDBEntry *acl, FlowSandeshData &fe_sandesh_data, Agent *agent) const
Definition: flow_entry.cc:3344
bool is_flags_set(const FlowEntryFlags &flags) const
Definition: flow_entry.h:611
bool l3_flow() const
Definition: flow_entry.h:599
@ DELETE_FLOW
Definition: flow_event.h:26
@ RECOMPUTE_FLOW
Definition: flow_event.h:45
virtual bool OperEntryAdd(FlowMgmtManager *mgr, const FlowMgmtRequest *req, FlowMgmtKey *key)
virtual bool CanDelete() const
uint32_t gen_id_
uint32_t Size() const
FlowList flow_list_
virtual bool Add(FlowEntry *flow, FlowMgmtKeyNode *node)
static const int MaxResponses
virtual bool OperEntryChange(FlowMgmtManager *mgr, const FlowMgmtRequest *req, FlowMgmtKey *key)
virtual bool Delete(FlowEntry *flow, FlowMgmtKeyNode *node)
virtual bool OperEntryDelete(FlowMgmtManager *mgr, const FlowMgmtRequest *req, FlowMgmtKey *key)
FlowEntry * flow_entry() const
void NonOperEntryEvent(FlowEvent::Event event, FlowEntry *flow)
Definition: flow_mgmt.cc:235
bool HasVrfFlows(uint32_t vrf)
Definition: flow_mgmt.cc:680
BgpAsAServiceFlowMgmtKey * FindBgpAsAServiceInfo(FlowEntry *flow, BgpAsAServiceFlowMgmtKey &key)
Definition: flow_mgmt.cc:725
void DBEntryEvent(FlowEvent::Event event, FlowMgmtKey *key, FlowEntry *flow)
Definition: flow_mgmt.cc:243
uint32_t gen_id() const
Event event() const
FlowEvent::Event GetResponseEvent() const
FlowMgmtManager * mgr() const
bool HandleNhChange(FlowMgmtManager *mgr, const FlowMgmtRequest *req, FlowMgmtKey *key)
bool RecomputeCoveringRouteEntry(FlowMgmtManager *mgr, InetRouteFlowMgmtKey *covering_route, InetRouteFlowMgmtKey *key)
bool NeedsReCompute(const FlowEntry *flow)
bool Delete(FlowEntry *flow, FlowMgmtKeyNode *node)
bool Add(FlowEntry *flow, FlowMgmtKeyNode *node)
void UpdateCounterOnDel(FlowEntry *flow, bool local_flow, bool old_ingress)
void UpdateCounterOnAdd(FlowEntry *flow, bool add_flow, bool local_flow, bool old_ingress)
uint32_t ingress_flow_count_
uint32_t egress_flow_count_
Definition: vrf.h:90
bool CanDelete() const
const VrfEntry * vrf_
VrfFlowMgmtEntry(VrfFlowMgmtTree *vrf_tree, const VrfEntry *vrf)
VrfFlowMgmtTree * vrf_tree_
static std::string UuidToString(const boost::uuids::uuid &id)
Definition: string_util.h:139
LifetimeRef< Data > table_ref_
Data(VrfFlowMgmtEntry *vrf_mgmt_entry, const VrfEntry *vrf, AgentRouteTable *table)