Line data Source code
1 : /*
2 : * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include <pkt/flow_mgmt/flow_mgmt_entry.h>
7 : #include <pkt/flow_event.h>
8 : #include <pkt/flow_mgmt/flow_mgmt_request.h>
9 : #include <pkt/flow_mgmt.h>
10 :
11 1201 : bool FlowMgmtEntry::Add(FlowEntry *flow, FlowMgmtKeyNode *node) {
12 1201 : if (node) {
13 798 : flow_list_.push_back(*node);
14 798 : return true;
15 : }
16 403 : return false;
17 : }
18 :
19 798 : bool FlowMgmtEntry::Delete(FlowEntry *flow, FlowMgmtKeyNode *node) {
20 1596 : flow_list_.erase(flow_list_.iterator_to(*node));
21 798 : 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
27 4372 : bool FlowMgmtEntry::CanDelete() const {
28 4372 : assert(oper_state_ != INVALID);
29 4372 : if (flow_list_.size())
30 653 : return false;
31 :
32 3719 : return (oper_state_ != OPER_ADD_SEEN);
33 : }
34 :
35 : // Handle Add/Change event for DBEntry
36 4976 : bool FlowMgmtEntry::OperEntryAdd(FlowMgmtManager *mgr,
37 : const FlowMgmtRequest *req, FlowMgmtKey *key) {
38 4976 : oper_state_ = OPER_ADD_SEEN;
39 4976 : FlowEvent::Event event = req->GetResponseEvent();
40 4976 : if (event == FlowEvent::INVALID)
41 74 : return false;
42 :
43 4902 : FlowList::iterator it = flow_list_.begin();
44 9920 : while (it != flow_list_.end()) {
45 58 : FlowMgmtKeyNode *node = &(*it);
46 58 : mgr->DBEntryEvent(event, key, node->flow_entry());
47 58 : it++;
48 : }
49 :
50 4902 : return true;
51 : }
52 :
53 11 : bool FlowMgmtEntry::OperEntryChange(FlowMgmtManager *mgr,
54 : const FlowMgmtRequest *req,
55 : FlowMgmtKey *key) {
56 11 : return OperEntryAdd(mgr, req, key);
57 : }
58 :
59 : // Handle Delete event for DBEntry
60 3564 : bool FlowMgmtEntry::OperEntryDelete(FlowMgmtManager *mgr,
61 : const FlowMgmtRequest *req,
62 : FlowMgmtKey *key) {
63 3564 : if (req->event() != FlowMgmtRequest::IMPLICIT_ROUTE_DELETE) {
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
67 3564 : oper_state_ = OPER_DEL_SEEN;
68 3564 : gen_id_ = req->gen_id();
69 : }
70 :
71 3564 : FlowEvent::Event event = req->GetResponseEvent();
72 3564 : if (event == FlowEvent::INVALID)
73 144 : return false;
74 :
75 3420 : FlowList::iterator it = flow_list_.begin();
76 7114 : while (it != flow_list_.end()) {
77 137 : FlowMgmtKeyNode *node = &(*it);
78 137 : mgr->DBEntryEvent(event, key, node->flow_entry());
79 137 : it++;
80 : }
81 :
82 3420 : return true;
83 : }
84 :
85 0 : string AclFlowMgmtEntry::GetAclFlowSandeshDataKey(const AclDBEntry *acl,
86 : const int last_count) const {
87 0 : string uuid_str = UuidToString(acl->GetUuid());
88 0 : std::stringstream ss;
89 0 : ss << uuid_str << ":";
90 0 : ss << last_count;
91 0 : return ss.str();
92 0 : }
93 :
94 0 : string AclFlowMgmtEntry::GetAceSandeshDataKey(const AclDBEntry *acl,
95 : const std::string &ace_id) {
96 0 : string uuid_str = UuidToString(acl->GetUuid());
97 0 : std::stringstream ss;
98 0 : ss << uuid_str << ":";
99 0 : ss << ace_id;
100 0 : return ss.str();
101 0 : }
102 :
103 0 : void AclFlowMgmtEntry::FillAceFlowSandeshInfo(const AclDBEntry *acl,
104 : AclFlowCountResp &data,
105 : const std::string& ace_id) {
106 0 : int count = 0;
107 0 : bool key_set = false;
108 0 : AceIdFlowCntMap::iterator aceid_it = aceid_cnt_map_.upper_bound(ace_id);
109 0 : std::vector<AceIdFlowCnt> id_cnt_l;
110 0 : while (aceid_it != aceid_cnt_map_.end()) {
111 0 : AceIdFlowCnt id_cnt_s;
112 0 : id_cnt_s.ace_id = aceid_it->first;
113 0 : id_cnt_s.flow_cnt = aceid_it->second;
114 0 : id_cnt_l.push_back(id_cnt_s);
115 0 : count++;
116 0 : ++aceid_it;
117 0 : if (count == MaxResponses && aceid_it != aceid_cnt_map_.end()) {
118 0 : data.set_iteration_key(GetAceSandeshDataKey(acl, id_cnt_s.ace_id));
119 0 : key_set = true;
120 0 : break;
121 : }
122 0 : }
123 0 : data.set_aceid_cnt_list(id_cnt_l);
124 :
125 0 : data.set_flow_count(Size());
126 0 : data.set_flow_miss(flow_miss_);
127 :
128 0 : if (!key_set) {
129 0 : data.set_iteration_key(GetAceSandeshDataKey(acl, Agent::NullString()));
130 : }
131 0 : }
132 :
133 0 : void AclFlowMgmtEntry::FillAclFlowSandeshInfo(const AclDBEntry *acl,
134 : AclFlowResp &data,
135 : const int last_count,
136 : Agent *agent) {
137 0 : int count = 0;
138 0 : bool key_set = false;
139 0 : FlowList::iterator fe_tree_it = flow_list_.begin();
140 0 : while (fe_tree_it != flow_list_.end() && (count + 1) < last_count) {
141 0 : fe_tree_it++;
142 0 : count++;
143 : }
144 0 : data.set_flow_count(Size());
145 0 : data.set_flow_miss(flow_miss_);
146 0 : std::vector<FlowSandeshData> flow_entries_l;
147 0 : while(fe_tree_it != flow_list_.end()) {
148 0 : FlowMgmtKeyNode *node = &(*fe_tree_it);
149 0 : const FlowEntry *fe = node->flow_entry();
150 0 : FlowSandeshData fe_sandesh_data;
151 0 : fe->SetAclFlowSandeshData(acl, fe_sandesh_data, agent);
152 :
153 0 : flow_entries_l.push_back(fe_sandesh_data);
154 0 : count++;
155 : ++fe_tree_it;
156 0 : if (count == (MaxResponses + last_count) &&
157 0 : fe_tree_it != flow_list_.end()) {
158 0 : data.set_iteration_key(GetAclFlowSandeshDataKey(acl, count));
159 0 : key_set = true;
160 0 : break;
161 : }
162 0 : }
163 0 : data.set_flow_entries(flow_entries_l);
164 0 : if (!key_set) {
165 0 : data.set_iteration_key(GetAclFlowSandeshDataKey(acl, 0));
166 : }
167 0 : }
168 :
169 29 : void AclFlowMgmtEntry::DecrementAceIdCountMap(const AclEntryIDList *id_list) {
170 29 : AclEntryIDList::const_iterator id_it;
171 51 : for (id_it = id_list->begin(); id_it != id_list->end(); ++id_it) {
172 22 : aceid_cnt_map_[id_it->id_] -= 1;
173 : }
174 29 : }
175 :
176 33 : bool AclFlowMgmtEntry::Add(const AclEntryIDList *id_list, FlowEntry *flow,
177 : const AclEntryIDList *old_id_list,
178 : FlowMgmtKeyNode *node) {
179 33 : if (old_id_list) {
180 25 : DecrementAceIdCountMap(old_id_list);
181 : }
182 33 : if (id_list->size()) {
183 25 : AclEntryIDList::const_iterator id_it;
184 50 : for (id_it = id_list->begin(); id_it != id_list->end(); ++id_it) {
185 25 : aceid_cnt_map_[id_it->id_] += 1;
186 : }
187 : } else {
188 8 : flow_miss_++;
189 : }
190 33 : return FlowMgmtEntry::Add(flow, node);
191 : }
192 :
193 8 : bool AclFlowMgmtEntry::Delete(const AclEntryIDList *id_list, FlowEntry *flow,
194 : FlowMgmtKeyNode *node) {
195 8 : if (id_list->size()) {
196 4 : DecrementAceIdCountMap(id_list);
197 : }
198 8 : return FlowMgmtEntry::Delete(flow, node);
199 : }
200 :
201 0 : bool BgpAsAServiceFlowMgmtEntry::NonOperEntryDelete(FlowMgmtManager *mgr,
202 : const FlowMgmtRequest *req,
203 : FlowMgmtKey *key) {
204 0 : oper_state_ = OPER_DEL_SEEN;
205 0 : gen_id_ = req->gen_id();
206 0 : FlowEvent::Event event = req->GetResponseEvent();
207 0 : if (event == FlowEvent::INVALID)
208 0 : return false;
209 :
210 0 : FlowList::iterator it = flow_list_.begin();
211 0 : while (it != flow_list_.end()) {
212 0 : FlowMgmtKeyNode *node = &(*it);
213 0 : mgr->NonOperEntryEvent(event, node->flow_entry());
214 0 : it++;
215 : }
216 0 : return true;
217 : }
218 :
219 : // Update health check on all the BgpAsAService flows
220 0 : bool BgpAsAServiceFlowMgmtEntry::HealthCheckUpdate(
221 : Agent *agent, FlowMgmtManager *mgr,
222 : BgpAsAServiceFlowMgmtKey &key,
223 : BgpAsAServiceFlowMgmtRequest *req) {
224 0 : for (FlowList::iterator it = flow_list_.begin();
225 0 : it != flow_list_.end(); ++it) {
226 0 : FlowMgmtKeyNode *node = &(*it);
227 : BgpAsAServiceFlowMgmtKey *bkey =
228 0 : mgr->FindBgpAsAServiceInfo(node->flow_entry(), key);
229 0 : if (bkey == NULL)
230 0 : continue;
231 :
232 0 : if (req->type() == BgpAsAServiceFlowMgmtRequest::HEALTH_CHECK_ADD)
233 0 : bkey->StartHealthCheck(agent, node->flow_entry(),
234 : req->health_check_uuid());
235 : else
236 0 : bkey->StopHealthCheck(node->flow_entry());
237 : }
238 0 : return true;
239 : }
240 :
241 226 : void VnFlowMgmtEntry::UpdateCounterOnAdd(FlowEntry *flow, bool add_flow,
242 : bool local_flow, bool old_ingress) {
243 226 : if (add_flow) {
244 142 : if (flow->is_flags_set(FlowEntry::LocalFlow)) {
245 18 : ingress_flow_count_++;
246 18 : egress_flow_count_++;
247 124 : } else if (flow->is_flags_set(FlowEntry::IngressDir)) {
248 61 : ingress_flow_count_++;
249 : } else {
250 63 : egress_flow_count_++;
251 : }
252 :
253 142 : return;
254 : }
255 :
256 84 : if (local_flow)
257 34 : return;
258 :
259 50 : bool new_ingress = flow->is_flags_set(FlowEntry::IngressDir);
260 50 : if (new_ingress != old_ingress) {
261 0 : if (new_ingress) {
262 0 : ingress_flow_count_++;
263 0 : egress_flow_count_--;
264 : } else {
265 0 : ingress_flow_count_--;
266 0 : egress_flow_count_++;
267 : }
268 : }
269 : }
270 :
271 142 : void VnFlowMgmtEntry::UpdateCounterOnDel(FlowEntry *flow, bool local_flow,
272 : bool old_ingress) {
273 142 : if (local_flow) {
274 16 : ingress_flow_count_--;
275 16 : egress_flow_count_--;
276 16 : return;
277 : }
278 :
279 126 : if (old_ingress) {
280 63 : ingress_flow_count_--;
281 : } else {
282 63 : egress_flow_count_--;
283 : }
284 : }
285 :
286 228 : bool InterfaceFlowMgmtEntry::Add(FlowEntry *flow, FlowMgmtKeyNode *node) {
287 228 : bool added = FlowMgmtEntry::Add(flow, node);
288 228 : if (added) {
289 144 : flow_created_++;
290 : }
291 228 : return added;
292 : }
293 :
294 144 : bool InterfaceFlowMgmtEntry::Delete(FlowEntry *flow, FlowMgmtKeyNode *node) {
295 144 : flow_aged_++;
296 144 : return FlowMgmtEntry::Delete(flow, node);
297 : }
298 :
299 850 : bool InetRouteFlowMgmtEntry::RecomputeCoveringRouteEntry
300 : (FlowMgmtManager *mgr, InetRouteFlowMgmtKey *covering_route,
301 : InetRouteFlowMgmtKey *key){
302 850 : FlowList::iterator it = flow_list_.begin();
303 1700 : while (it != flow_list_.end()) {
304 0 : FlowMgmtKeyNode *node = &(*it);
305 : // Queue the DB Event only route key matches src or dst ip matches.
306 0 : if (key->NeedsReCompute(node->flow_entry())) {
307 0 : mgr->DBEntryEvent(FlowEvent::RECOMPUTE_FLOW, covering_route,
308 : node->flow_entry());
309 : }
310 0 : it++;
311 : }
312 :
313 850 : return true;
314 : }
315 :
316 4 : bool InetRouteFlowMgmtEntry::HandleNhChange(FlowMgmtManager *mgr,
317 : const FlowMgmtRequest *req,
318 : FlowMgmtKey *key) {
319 4 : assert(req->event() == FlowMgmtRequest::DELETE_LAYER2_FLOW);
320 :
321 4 : FlowList::iterator it = flow_list_.begin();
322 20 : while (it != flow_list_.end()) {
323 : FlowEvent::Event event;
324 6 : FlowMgmtKeyNode *node = &(*it);
325 6 : it++;
326 6 : FlowEntry *fe = node->flow_entry();
327 6 : if (fe->l3_flow()) {
328 6 : event = FlowEvent::RECOMPUTE_FLOW;
329 : } else {
330 0 : event = FlowEvent::DELETE_FLOW;
331 : }
332 :
333 6 : mgr->DBEntryEvent(event, key, fe);
334 : }
335 :
336 4 : return true;
337 : }
338 :
339 74 : VrfFlowMgmtEntry::VrfFlowMgmtEntry(VrfFlowMgmtTree *vrf_tree,
340 74 : const VrfEntry *vrf) :
341 148 : vrf_(vrf), vrf_id_(vrf->vrf_id()),
342 74 : inet4_(this, vrf, vrf->GetRouteTable(Agent::INET4_UNICAST)),
343 74 : inet6_(this, vrf, vrf->GetRouteTable(Agent::INET6_UNICAST)),
344 74 : bridge_(this, vrf, vrf->GetRouteTable(Agent::BRIDGE)),
345 74 : vrf_tree_(vrf_tree) {
346 74 : }
347 :
348 154 : bool VrfFlowMgmtEntry::CanDelete() const {
349 154 : if (FlowMgmtEntry::CanDelete() == false)
350 0 : return false;
351 :
352 228 : if (inet4_.deleted() == false || inet6_.deleted() == false ||
353 74 : bridge_.deleted() == false) {
354 80 : return false;
355 : }
356 :
357 74 : return (vrf_tree_->mgr()->HasVrfFlows(vrf_id_) == false);
358 : }
359 :
360 222 : VrfFlowMgmtEntry::Data::Data(VrfFlowMgmtEntry *vrf_mgmt_entry,
361 222 : const VrfEntry *vrf, AgentRouteTable *table) :
362 222 : deleted_(false), table_ref_(this, NULL),
363 222 : vrf_mgmt_entry_(vrf_mgmt_entry), vrf_(vrf) {
364 222 : if (vrf->IsDeleted() == false) {
365 222 : table_ref_.Reset(table->deleter());
366 : } else {
367 0 : deleted_ = true;
368 : }
369 222 : }
370 :
371 222 : VrfFlowMgmtEntry::Data::~Data() {
372 222 : table_ref_.Reset(NULL);
373 222 : }
374 :
375 222 : void VrfFlowMgmtEntry::Data::ManagedDelete() {
376 222 : deleted_ = true;
377 222 : vrf_mgmt_entry_->vrf_tree()->mgr()->RetryVrfDeleteEvent(vrf_);
378 222 : }
|