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