Line data Source code
1 : #include <bitset>
2 : #include <boost/uuid/uuid_io.hpp>
3 : #include "cmn/agent.h"
4 : #include "controller/controller_init.h"
5 : #include "oper/bgp_as_service.h"
6 : #include "oper/health_check.h"
7 : #include "pkt/flow_proto.h"
8 : #include <pkt/flow_mgmt.h>
9 : #include <pkt/flow_mgmt/flow_mgmt_entry.h>
10 : #include <pkt/flow_mgmt/flow_entry_info.h>
11 : #include <pkt/flow_mgmt/flow_mgmt_request.h>
12 : #include <pkt/flow_mgmt/flow_mgmt_dbclient.h>
13 : #include "uve/flow_uve_stats_request.h"
14 : #include "uve/agent_uve_stats.h"
15 : #include "vrouter/flow_stats/flow_stats_collector.h"
16 :
17 : FlowMgmtManager::FlowMgmtQueue *FlowMgmtManager::log_queue_;
18 : /////////////////////////////////////////////////////////////////////////////
19 : // FlowMgmtManager methods
20 : /////////////////////////////////////////////////////////////////////////////
21 2 : FlowMgmtManager::FlowMgmtManager(Agent *agent, uint16_t table_index) :
22 2 : agent_(agent),
23 2 : table_index_(table_index),
24 2 : acl_flow_mgmt_tree_(this),
25 2 : interface_flow_mgmt_tree_(this),
26 2 : vn_flow_mgmt_tree_(this),
27 2 : ip4_route_flow_mgmt_tree_(this),
28 2 : ip6_route_flow_mgmt_tree_(this),
29 2 : bridge_route_flow_mgmt_tree_(this),
30 2 : vrf_flow_mgmt_tree_(this),
31 2 : nh_flow_mgmt_tree_(this),
32 2 : flow_mgmt_dbclient_(new FlowMgmtDbClient(agent, this)),
33 2 : request_queue_(agent_->task_scheduler()->GetTaskId(kTaskFlowMgmt),
34 : table_index,
35 : boost::bind(&FlowMgmtManager::RequestHandler, this, _1)),
36 2 : db_event_queue_(agent_->task_scheduler()->GetTaskId(kTaskFlowMgmt),
37 : table_index,
38 : boost::bind(&FlowMgmtManager::DBRequestHandler, this, _1),
39 8 : db_event_queue_.kMaxSize, 1) {
40 2 : request_queue_.set_name("Flow management");
41 2 : request_queue_.set_measure_busy_time(agent->MeasureQueueDelay());
42 2 : db_event_queue_.set_name("Flow DB Event Queue");
43 6 : for (uint8_t count = 0; count < MAX_XMPP_SERVERS; count++) {
44 4 : bgp_as_a_service_flow_mgmt_tree_[count].reset(
45 4 : new BgpAsAServiceFlowMgmtTree(this, count));
46 : }
47 2 : }
48 :
49 2 : void FlowMgmtManager::Init() {
50 2 : flow_mgmt_dbclient_->Init();
51 2 : agent_->acl_table()->set_ace_flow_sandesh_data_cb
52 2 : (boost::bind(&FlowMgmtManager::SetAceSandeshData, this, _1, _2, _3));
53 2 : agent_->acl_table()->set_acl_flow_sandesh_data_cb
54 2 : (boost::bind(&FlowMgmtManager::SetAclFlowSandeshData, this, _1, _2,
55 : _3));
56 : // If BGP service is deleted then flush off all the flows for the VMI.
57 2 : agent_->oper_db()->bgp_as_a_service()->RegisterServiceDeleteCb(boost::bind
58 : (&FlowMgmtManager::BgpAsAServiceNotify, this, _1, _2));
59 : // If BGP service health check configuration is modified,
60 : // update the corresponding flows
61 2 : agent_->oper_db()->bgp_as_a_service()->RegisterHealthCheckCb(boost::bind
62 : (&FlowMgmtManager::BgpAsAServiceHealthCheckNotify, this,
63 : _1, _2, _3, _4));
64 : // If control node goes off delete all flows frmo its tree.
65 2 : agent_->controller()->RegisterControllerChangeCallback(boost::bind
66 : (&FlowMgmtManager::ControllerNotify, this, _1));
67 2 : }
68 :
69 2 : void FlowMgmtManager::Shutdown() {
70 2 : request_queue_.Shutdown();
71 2 : db_event_queue_.Shutdown();
72 2 : flow_mgmt_dbclient_->Shutdown();
73 2 : }
74 :
75 2 : void FlowMgmtManager::InitLogQueue(Agent *agent) {
76 2 : uint32_t task_id = agent->task_scheduler()->GetTaskId(kTaskFlowLogging);
77 4 : log_queue_ = new FlowMgmtQueue(task_id, 0,
78 : boost::bind(&FlowMgmtManager::LogHandler,
79 2 : _1));
80 2 : log_queue_->set_name("Flow Log Queue");
81 2 : log_queue_->SetBounded(true);
82 2 : }
83 :
84 2 : void FlowMgmtManager::ShutdownLogQueue() {
85 2 : log_queue_->Shutdown();
86 2 : delete log_queue_;
87 2 : }
88 :
89 : /////////////////////////////////////////////////////////////////////////////
90 : // BGP as a service callbacks
91 : /////////////////////////////////////////////////////////////////////////////
92 0 : void FlowMgmtManager::BgpAsAServiceNotify(const boost::uuids::uuid &vm_uuid,
93 : uint32_t source_port) {
94 : FlowMgmtRequestPtr req(new BgpAsAServiceFlowMgmtRequest(vm_uuid,
95 0 : source_port));
96 0 : request_queue_.Enqueue(req);
97 0 : }
98 :
99 0 : void FlowMgmtManager::BgpAsAServiceHealthCheckNotify(
100 : const boost::uuids::uuid &vm_uuid, uint32_t source_port,
101 : const boost::uuids::uuid &hc_uuid, bool add) {
102 0 : BgpAsAServiceFlowMgmtRequest::Type type = add ?
103 : BgpAsAServiceFlowMgmtRequest::HEALTH_CHECK_ADD :
104 : BgpAsAServiceFlowMgmtRequest::HEALTH_CHECK_DEL;
105 : FlowMgmtRequestPtr req(new BgpAsAServiceFlowMgmtRequest(vm_uuid,
106 : source_port,
107 0 : hc_uuid, type));
108 0 : request_queue_.Enqueue(req);
109 0 : }
110 :
111 21 : void FlowMgmtManager::ControllerNotify(uint8_t index) {
112 21 : FlowMgmtRequestPtr req(new BgpAsAServiceFlowMgmtRequest(index));
113 21 : request_queue_.Enqueue(req);
114 21 : }
115 :
116 : /////////////////////////////////////////////////////////////////////////////
117 : // Introspect routines
118 : /////////////////////////////////////////////////////////////////////////////
119 0 : void FlowMgmtManager::SetAceSandeshData(const AclDBEntry *acl,
120 : AclFlowCountResp &data,
121 : const std::string &ace_id) {
122 0 : AclFlowMgmtKey key(acl, NULL);
123 : AclFlowMgmtEntry *entry = static_cast<AclFlowMgmtEntry *>
124 0 : (acl_flow_mgmt_tree_.Find(&key));
125 0 : if (entry == NULL) {
126 0 : return;
127 : }
128 0 : entry->FillAceFlowSandeshInfo(acl, data, ace_id);
129 :
130 0 : }
131 :
132 0 : void FlowMgmtManager::SetAclFlowSandeshData(const AclDBEntry *acl,
133 : AclFlowResp &data,
134 : const int last_count) {
135 0 : AclFlowMgmtKey key(acl, NULL);
136 : AclFlowMgmtEntry *entry = static_cast<AclFlowMgmtEntry *>
137 0 : (acl_flow_mgmt_tree_.Find(&key));
138 0 : if (entry == NULL) {
139 0 : return;
140 : }
141 0 : entry->FillAclFlowSandeshInfo(acl, data, last_count, agent_);
142 0 : }
143 :
144 : /////////////////////////////////////////////////////////////////////////////
145 : // Utility methods to enqueue events into work-queue
146 : /////////////////////////////////////////////////////////////////////////////
147 230 : void FlowMgmtManager::AddEvent(FlowEntry *flow) {
148 : // Check if there is a flow-mgmt request already pending
149 : // Flow mgmt takes care of current state of flow. So, there is no need to
150 : // enqueue duplicate requests
151 230 : FlowMgmtRequest *req = flow->flow_mgmt_request();
152 230 : if (req == NULL) {
153 150 : req = new FlowMgmtRequest(FlowMgmtRequest::UPDATE_FLOW, flow);
154 150 : flow->set_flow_mgmt_request(req);
155 150 : request_queue_.Enqueue(FlowMgmtRequestPtr(req));
156 : }
157 230 : }
158 :
159 224 : void FlowMgmtManager::DeleteEvent(FlowEntry *flow,
160 : const RevFlowDepParams ¶ms) {
161 : // Check if there is a flow-mgmt request already pending
162 : // Flow mgmt takes care of current state of flow. So, there is no need to
163 : // enqueue duplicate requests
164 224 : FlowMgmtRequest *req = flow->flow_mgmt_request();
165 224 : if (req == NULL) {
166 224 : req = new FlowMgmtRequest(FlowMgmtRequest::UPDATE_FLOW, flow);
167 224 : flow->set_flow_mgmt_request(req);
168 224 : request_queue_.Enqueue(FlowMgmtRequestPtr(req));
169 : }
170 :
171 224 : req->set_params(params);
172 224 : }
173 :
174 36 : void FlowMgmtManager::FlowStatsUpdateEvent(FlowEntry *flow, uint32_t bytes,
175 : uint32_t packets,
176 : uint32_t oflow_bytes,
177 : const boost::uuids::uuid &u) {
178 36 : if (bytes == 0 && packets == 0 && oflow_bytes == 0) {
179 36 : return;
180 : }
181 :
182 : /* Ignore StatsUpdate request in TSN mode as we don't export flows */
183 0 : if (agent_->tsn_enabled()) {
184 0 : return;
185 : }
186 : FlowMgmtRequestPtr req(new FlowMgmtRequest
187 : (FlowMgmtRequest::UPDATE_FLOW_STATS, flow,
188 0 : bytes, packets, oflow_bytes, u));
189 0 : request_queue_.Enqueue(req);
190 0 : }
191 :
192 222 : void FlowMgmtManager::RetryVrfDeleteEvent(const VrfEntry *vrf) {
193 : FlowMgmtRequestPtr req(new FlowMgmtRequest
194 222 : (FlowMgmtRequest::RETRY_DELETE_VRF, vrf, 0));
195 222 : request_queue_.Enqueue(req);
196 222 : }
197 :
198 0 : void FlowMgmtManager::DummyEvent() {
199 0 : FlowMgmtRequestPtr req(new FlowMgmtRequest(FlowMgmtRequest::DUMMY));
200 0 : request_queue_.Enqueue(req);
201 0 : }
202 :
203 4965 : void FlowMgmtManager::AddDBEntryEvent(const DBEntry *entry, uint32_t gen_id) {
204 : FlowMgmtRequestPtr req(new FlowMgmtRequest(FlowMgmtRequest::ADD_DBENTRY,
205 4965 : entry, gen_id));
206 4965 : db_event_queue_.Enqueue(req);
207 4965 : }
208 :
209 11 : void FlowMgmtManager::ChangeDBEntryEvent(const DBEntry *entry,
210 : uint32_t gen_id) {
211 : FlowMgmtRequestPtr req(new FlowMgmtRequest(FlowMgmtRequest::CHANGE_DBENTRY,
212 11 : entry, gen_id));
213 11 : db_event_queue_.Enqueue(req);
214 11 : }
215 :
216 3564 : void FlowMgmtManager::DeleteDBEntryEvent(const DBEntry *entry,
217 : uint32_t gen_id) {
218 : FlowMgmtRequestPtr req(new FlowMgmtRequest(FlowMgmtRequest::DELETE_DBENTRY,
219 3564 : entry, gen_id));
220 3564 : db_event_queue_.Enqueue(req);
221 3564 : }
222 :
223 4 : void FlowMgmtManager::RouteNHChangeEvent(const DBEntry *entry,
224 : uint32_t gen_id) {
225 : FlowMgmtRequestPtr req(new FlowMgmtRequest
226 : (FlowMgmtRequest::DELETE_LAYER2_FLOW,
227 4 : entry, gen_id));
228 4 : db_event_queue_.Enqueue(req);
229 4 : }
230 :
231 3695 : void FlowMgmtManager::EnqueueFlowEvent(FlowEvent *event) {
232 3695 : agent_->pkt()->get_flow_proto()->EnqueueFlowEvent(event);
233 3695 : }
234 :
235 0 : void FlowMgmtManager::NonOperEntryEvent(FlowEvent::Event event,
236 : FlowEntry *flow) {
237 0 : FlowEvent *flow_resp = new FlowEvent(event, flow->key(), true,
238 0 : FlowTable::kPortNatFlowTableInstance);
239 0 : flow_resp->set_flow(flow);
240 0 : EnqueueFlowEvent(flow_resp);
241 0 : }
242 :
243 201 : void FlowMgmtManager::DBEntryEvent(FlowEvent::Event event, FlowMgmtKey *key,
244 : FlowEntry *flow) {
245 201 : FlowEvent *flow_resp = new FlowEvent(event, NULL, key->db_entry());
246 201 : key->KeyToFlowRequest(flow_resp);
247 201 : flow_resp->set_flow(flow);
248 201 : EnqueueFlowEvent(flow_resp);
249 201 : }
250 :
251 3494 : void FlowMgmtManager::FreeDBEntryEvent(FlowEvent::Event event, FlowMgmtKey *key,
252 : uint32_t gen_id) {
253 3494 : FlowEvent *flow_resp = new FlowEvent(event, table_index_, key->db_entry(),
254 3494 : gen_id);
255 3494 : EnqueueFlowEvent(flow_resp);
256 3494 : }
257 :
258 0 : void FlowMgmtManager::FlowUpdateQueueDisable(bool disabled) {
259 0 : request_queue_.set_disable(disabled);
260 0 : db_event_queue_.set_disable(disabled);
261 0 : }
262 :
263 0 : size_t FlowMgmtManager::FlowUpdateQueueLength() {
264 0 : return request_queue_.Length();
265 : }
266 :
267 0 : size_t FlowMgmtManager::FlowDBQueueLength() {
268 0 : return db_event_queue_.Length();
269 : }
270 : /////////////////////////////////////////////////////////////////////////////
271 : // Handlers for events from the work-queue
272 : /////////////////////////////////////////////////////////////////////////////
273 8544 : bool FlowMgmtManager::ProcessEvent(FlowMgmtRequest *req, FlowMgmtKey *key,
274 : FlowMgmtTree *tree) {
275 8544 : InetRouteFlowMgmtTree* itree = dynamic_cast<InetRouteFlowMgmtTree*>(tree);
276 8544 : switch (req->event()) {
277 4965 : case FlowMgmtRequest::ADD_DBENTRY:
278 4965 : tree->OperEntryAdd(req, key);
279 4965 : break;
280 :
281 11 : case FlowMgmtRequest::CHANGE_DBENTRY:
282 11 : tree->OperEntryChange(req, key);
283 11 : break;
284 :
285 3564 : case FlowMgmtRequest::DELETE_DBENTRY:
286 : case FlowMgmtRequest::IMPLICIT_ROUTE_DELETE:
287 3564 : tree->OperEntryDelete(req, key);
288 3564 : break;
289 :
290 4 : case FlowMgmtRequest::DELETE_LAYER2_FLOW:
291 4 : assert(itree);
292 4 : itree->RouteNHChangeEvent(req, key);
293 4 : break;
294 :
295 0 : default:
296 0 : assert(0);
297 : break;
298 : }
299 :
300 8544 : return true;
301 : }
302 :
303 8544 : bool FlowMgmtManager::DBRequestHandler(FlowMgmtRequest *req,
304 : const DBEntry *entry) {
305 8544 : const Interface *intf = dynamic_cast<const Interface *>(entry);
306 8544 : if (intf) {
307 682 : InterfaceFlowMgmtKey key(intf);
308 682 : return ProcessEvent(req, &key, &interface_flow_mgmt_tree_);
309 682 : }
310 :
311 7862 : const VnEntry *vn = dynamic_cast<const VnEntry *>(entry);
312 7862 : if (vn) {
313 140 : VnFlowMgmtKey key(vn);
314 140 : return ProcessEvent(req, &key, &vn_flow_mgmt_tree_);
315 140 : }
316 :
317 7722 : const AclDBEntry *acl = dynamic_cast<const AclDBEntry *>(entry);
318 7722 : if (acl) {
319 12 : AclFlowMgmtKey key(acl, NULL);
320 12 : return ProcessEvent(req, &key, &acl_flow_mgmt_tree_);
321 12 : }
322 :
323 7710 : const NextHop *nh = dynamic_cast<const NextHop *>(entry);
324 7710 : if (nh) {
325 3300 : NhFlowMgmtKey key(static_cast<const NextHop *>(req->db_entry()));
326 3300 : return ProcessEvent(req, &key, &nh_flow_mgmt_tree_);
327 3300 : }
328 :
329 : const InetUnicastRouteEntry *inet_uc_rt =
330 4410 : dynamic_cast<const InetUnicastRouteEntry *>(entry);
331 4410 : if (inet_uc_rt) {
332 2856 : InetRouteFlowMgmtKey key(inet_uc_rt);
333 2856 : if (inet_uc_rt->prefix_address().is_v4()) {
334 1761 : return ProcessEvent(req, &key, &ip4_route_flow_mgmt_tree_);
335 : }
336 1095 : if (inet_uc_rt->prefix_address().is_v6()) {
337 1095 : return ProcessEvent(req, &key, &ip6_route_flow_mgmt_tree_);
338 : }
339 2856 : }
340 :
341 : const BridgeRouteEntry *bridge =
342 1554 : dynamic_cast<const BridgeRouteEntry *>(entry);
343 1554 : if (bridge) {
344 1336 : BridgeRouteFlowMgmtKey key(bridge);
345 1336 : return ProcessEvent(req, &key, &bridge_route_flow_mgmt_tree_);
346 1336 : }
347 :
348 218 : const VrfEntry *vrf = dynamic_cast<const VrfEntry *>(entry);
349 218 : if (vrf) {
350 218 : VrfFlowMgmtKey key(vrf);
351 218 : return ProcessEvent(req, &key, &vrf_flow_mgmt_tree_);
352 218 : }
353 :
354 0 : assert(0);
355 : return true;
356 : }
357 :
358 : bool
359 21 : FlowMgmtManager::BgpAsAServiceRequestHandler(FlowMgmtRequest *req) {
360 :
361 : BgpAsAServiceFlowMgmtRequest *bgp_as_a_service_request =
362 21 : dynamic_cast<BgpAsAServiceFlowMgmtRequest *>(req);
363 21 : if (bgp_as_a_service_request->type() == BgpAsAServiceFlowMgmtRequest::VMI) {
364 : //Delete it for for all CN trees
365 0 : for (uint8_t count = 0; count < MAX_XMPP_SERVERS; count++) {
366 : BgpAsAServiceFlowMgmtKey key(bgp_as_a_service_request->vm_uuid(),
367 : bgp_as_a_service_request->source_port(),
368 0 : count, NULL, NULL);
369 0 : bgp_as_a_service_flow_mgmt_tree_[count].get()->
370 0 : BgpAsAServiceDelete(key, req);
371 0 : }
372 21 : } else if (bgp_as_a_service_request->type() ==
373 : BgpAsAServiceFlowMgmtRequest::CONTROLLER) {
374 21 : bgp_as_a_service_flow_mgmt_tree_[bgp_as_a_service_request->index()].get()->
375 21 : DeleteAll();
376 0 : } else if (bgp_as_a_service_request->type() ==
377 0 : BgpAsAServiceFlowMgmtRequest::HEALTH_CHECK_ADD ||
378 0 : bgp_as_a_service_request->type() ==
379 : BgpAsAServiceFlowMgmtRequest::HEALTH_CHECK_DEL) {
380 : // Health check added to BGPaaS, check if any flows are impacted
381 0 : for (uint8_t count = 0; count < MAX_XMPP_SERVERS; count++) {
382 : BgpAsAServiceFlowMgmtKey key(bgp_as_a_service_request->vm_uuid(),
383 : bgp_as_a_service_request->source_port(),
384 0 : count, NULL, NULL);
385 0 : bgp_as_a_service_flow_mgmt_tree_[count].get()->
386 0 : BgpAsAServiceHealthCheckUpdate(agent(), key, bgp_as_a_service_request);
387 0 : }
388 : }
389 :
390 21 : return true;
391 : }
392 :
393 617 : bool FlowMgmtManager::RequestHandler(FlowMgmtRequestPtr req) {
394 617 : switch (req->event()) {
395 374 : case FlowMgmtRequest::UPDATE_FLOW: {
396 374 : FlowEntry *flow = req->flow().get();
397 : // Before processing event, set the request pointer in flow to
398 : // NULL. This ensures flow-entry enqueues new request from now
399 : // onwards
400 374 : std::scoped_lock mutex(flow->mutex());
401 374 : flow->set_flow_mgmt_request(NULL);
402 :
403 : // Update flow-mgmt information based on flow-state
404 374 : if (flow->deleted() == false) {
405 : FlowMgmtRequestPtr log_req(new FlowMgmtRequest
406 : (FlowMgmtRequest::ADD_FLOW,
407 230 : req->flow().get()));
408 230 : log_queue_->Enqueue(log_req);
409 :
410 : //Enqueue Add request to flow-stats-collector
411 230 : agent_->flow_stats_manager()->AddEvent(req->flow());
412 :
413 : //Enqueue Add request to UVE module for ACE stats
414 230 : EnqueueUveAddEvent(flow);
415 :
416 230 : AddFlow(req->flow());
417 :
418 230 : } else {
419 : FlowMgmtRequestPtr log_req(new FlowMgmtRequest
420 : (FlowMgmtRequest::DELETE_FLOW,
421 144 : req->flow().get(), req->params()));
422 144 : log_queue_->Enqueue(log_req);
423 :
424 : //Enqueue Delete request to flow-stats-collector
425 144 : agent_->flow_stats_manager()->DeleteEvent(flow, req->params());
426 :
427 : //Enqueue Delete request to UVE module for ACE stats
428 144 : EnqueueUveDeleteEvent(flow);
429 :
430 144 : DeleteFlow(req->flow(), req->params());
431 144 : }
432 374 : break;
433 374 : }
434 :
435 0 : case FlowMgmtRequest::UPDATE_FLOW_STATS: {
436 : //Handle Flow stats update for flow-mgmt
437 0 : UpdateFlowStats(req->flow(), req->bytes(), req->packets(),
438 0 : req->oflow_bytes(), req->flow_uuid());
439 0 : break;
440 : }
441 :
442 222 : case FlowMgmtRequest::RETRY_DELETE_VRF: {
443 222 : RetryVrfDelete(req->vrf_id());
444 222 : break;
445 : }
446 :
447 21 : case FlowMgmtRequest::DELETE_BGP_AAS_FLOWS: {
448 21 : BgpAsAServiceRequestHandler(req.get());
449 21 : break;
450 : }
451 :
452 0 : case FlowMgmtRequest::DUMMY:
453 0 : break;
454 :
455 0 : default:
456 0 : assert(0);
457 :
458 : }
459 :
460 617 : return true;
461 : }
462 :
463 8544 : bool FlowMgmtManager::DBRequestHandler(FlowMgmtRequestPtr req) {
464 8544 : switch (req->event()) {
465 8544 : case FlowMgmtRequest::ADD_DBENTRY:
466 : case FlowMgmtRequest::CHANGE_DBENTRY:
467 : case FlowMgmtRequest::DELETE_DBENTRY:
468 : case FlowMgmtRequest::DELETE_LAYER2_FLOW: {
469 8544 : DBRequestHandler(req.get(), req->db_entry());
470 8544 : break;
471 : }
472 :
473 0 : default:
474 0 : assert(0);
475 :
476 : }
477 :
478 8544 : return true;
479 : }
480 :
481 374 : bool FlowMgmtManager::LogHandler(FlowMgmtRequestPtr req) {
482 374 : FlowEntry *flow = req->flow().get();
483 374 : FlowEntry *rflow = flow->reverse_flow_entry();
484 :
485 518 : FLOW_LOCK(flow, rflow, FlowEvent::FLOW_MESSAGE);
486 374 : switch (req->event()) {
487 230 : case FlowMgmtRequest::ADD_FLOW: {
488 230 : LogFlowUnlocked(flow, "ADD");
489 230 : break;
490 : }
491 :
492 144 : case FlowMgmtRequest::DELETE_FLOW: {
493 144 : LogFlowUnlocked(flow, "DEL");
494 144 : break;
495 : }
496 :
497 0 : default:
498 0 : assert(0);
499 :
500 : }
501 :
502 374 : return true;
503 374 : }
504 :
505 1936 : void FlowMgmtManager::RetryVrfDelete(uint32_t vrf_id) {
506 1936 : vrf_flow_mgmt_tree_.RetryDelete(vrf_id);
507 1936 : }
508 :
509 : // Extract all the FlowMgmtKey for a flow
510 374 : void FlowMgmtManager::LogFlowUnlocked(FlowEntry *flow, const std::string &op) {
511 374 : if (flow->trace() == false)
512 123 : return;
513 251 : FlowInfo trace;
514 251 : flow->FillFlowInfo(trace);
515 251 : FLOW_TRACE(Trace, op, trace);
516 251 : }
517 :
518 : // Extract all the FlowMgmtKey for a flow
519 230 : void FlowMgmtManager::MakeFlowMgmtKeyTree(FlowEntry *flow,
520 : FlowMgmtKeyTree *tree) {
521 230 : acl_flow_mgmt_tree_.ExtractKeys(flow, tree);
522 230 : interface_flow_mgmt_tree_.ExtractKeys(flow, tree);
523 230 : vn_flow_mgmt_tree_.ExtractKeys(flow, tree);
524 230 : ip4_route_flow_mgmt_tree_.ExtractKeys(flow, tree);
525 230 : ip6_route_flow_mgmt_tree_.ExtractKeys(flow, tree);
526 230 : bridge_route_flow_mgmt_tree_.ExtractKeys(flow, tree);
527 230 : nh_flow_mgmt_tree_.ExtractKeys(flow, tree);
528 230 : if (flow->is_flags_set(FlowEntry::BgpRouterService)) {
529 0 : int cn_index = BgpAsAServiceFlowMgmtTree::GetCNIndex(flow);
530 0 : if (cn_index != BgpAsAServiceFlowMgmtTree::kInvalidCnIndex) {
531 0 : bgp_as_a_service_flow_mgmt_tree_[cn_index].get()->
532 0 : ExtractKeys(flow, tree);
533 : }
534 : }
535 230 : }
536 :
537 230 : void FlowMgmtManager::EnqueueUveAddEvent(const FlowEntry *flow) const {
538 230 : AgentUveStats *uve = dynamic_cast<AgentUveStats *>(agent_->uve());
539 230 : if (uve) {
540 230 : const Interface *itf = flow->intf_entry();
541 230 : const VmInterface *vmi = dynamic_cast<const VmInterface *>(itf);
542 230 : const VnEntry *vn = flow->vn_entry();
543 230 : string vn_name = vn? vn->GetName() : "";
544 230 : string itf_name = vmi? vmi->cfg_name() : "";
545 230 : FlowUveVnAcePolicyInfo vn_ace_info;
546 230 : FlowUveFwPolicyInfo fw_policy_info;
547 :
548 230 : flow->FillUveVnAceInfo(&vn_ace_info);
549 230 : if (!itf_name.empty()) {
550 226 : flow->FillUveFwStatsInfo(&fw_policy_info, true);
551 : }
552 : boost::shared_ptr<FlowUveStatsRequest> req(new FlowUveStatsRequest
553 230 : (FlowUveStatsRequest::ADD_FLOW, flow->uuid(), itf_name,
554 230 : flow->sg_rule_uuid(), vn_ace_info, fw_policy_info));
555 :
556 234 : if (!req->sg_info_valid() && !req->vn_ace_valid() &&
557 4 : !req->fw_policy_valid()) {
558 4 : return;
559 : }
560 :
561 226 : uve->stats_manager()->EnqueueEvent(req);
562 246 : }
563 : }
564 :
565 152 : void FlowMgmtManager::EnqueueUveDeleteEvent(const FlowEntry *flow) const {
566 152 : AgentUveStats *uve = dynamic_cast<AgentUveStats *>(agent_->uve());
567 152 : if (uve) {
568 152 : const Interface *itf = flow->intf_entry();
569 152 : const VmInterface *vmi = dynamic_cast<const VmInterface *>(itf);
570 152 : string itf_name = vmi? vmi->cfg_name() : "";
571 152 : FlowUveFwPolicyInfo fw_policy_info;
572 152 : if (!itf_name.empty()) {
573 101 : flow->FillUveFwStatsInfo(&fw_policy_info, false);
574 : }
575 : boost::shared_ptr<FlowUveStatsRequest> req(new FlowUveStatsRequest
576 152 : (FlowUveStatsRequest::DELETE_FLOW, flow->uuid(), itf_name,
577 152 : fw_policy_info));
578 152 : uve->stats_manager()->EnqueueEvent(req);
579 152 : }
580 152 : }
581 :
582 230 : void FlowMgmtManager::AddFlow(FlowEntryPtr &flow) {
583 230 : FlowMgmtKeyTree new_tree;
584 230 : MakeFlowMgmtKeyTree(flow.get(), &new_tree);
585 :
586 : // Get old FlowMgmtKeyTree
587 230 : FlowEntryInfo *old_info = LocateFlowEntryInfo(flow);
588 230 : FlowMgmtKeyTree *old_tree = &old_info->tree_;
589 230 : assert(old_tree);
590 230 : old_info->count_++;
591 :
592 : // Apply the difference in old and new key tree
593 230 : FlowMgmtKeyTree::iterator new_it = new_tree.begin();
594 230 : FlowMgmtKeyTree::iterator old_it = old_tree->begin();
595 :
596 680 : while (new_it != new_tree.end() && old_it != old_tree->end()) {
597 450 : FlowMgmtKey *new_key = new_it->first;
598 450 : FlowMgmtKey *old_key = old_it->first;
599 450 : if (new_key->IsLess(old_key)) {
600 13 : AddFlowMgmtKey(flow.get(), old_info, new_key, NULL);
601 13 : new_it++;
602 437 : } else if (old_key->IsLess(new_key)) {
603 34 : FlowMgmtKeyNode *node = old_it->second;
604 34 : DeleteFlowMgmtKey(flow.get(), old_info, old_key,
605 : node);
606 34 : FlowMgmtKeyTree::iterator tmp = old_it++;
607 34 : FlowMgmtKey *key = tmp->first;
608 34 : old_tree->erase(tmp);
609 34 : delete key;
610 34 : delete node;
611 : } else {
612 403 : AddFlowMgmtKey(flow.get(), old_info, new_key, old_key);
613 403 : old_it++;
614 403 : new_it++;
615 : }
616 : }
617 :
618 1015 : while (new_it != new_tree.end()) {
619 785 : FlowMgmtKey *new_key = new_it->first;
620 785 : AddFlowMgmtKey(flow.get(), old_info, new_key, NULL);
621 785 : new_it++;
622 : }
623 :
624 264 : while (old_it != old_tree->end()) {
625 34 : FlowMgmtKey *old_key = old_it->first;
626 34 : FlowMgmtKeyNode *node = old_it->second;
627 34 : DeleteFlowMgmtKey(flow.get(), old_info, old_key, node);
628 34 : FlowMgmtKeyTree::iterator tmp = old_it++;
629 34 : FlowMgmtKey *key = tmp->first;
630 34 : old_tree->erase(tmp);
631 34 : delete key;
632 34 : delete node;
633 : }
634 :
635 230 : new_it = new_tree.begin();
636 1431 : while (new_it != new_tree.end()) {
637 1201 : FlowMgmtKeyTree::iterator tmp = new_it++;
638 1201 : FlowMgmtKey *key = tmp->first;
639 1201 : FlowMgmtKeyNode *node = tmp->second;
640 1201 : new_tree.erase(tmp);
641 1201 : delete key;
642 1201 : delete node;
643 : }
644 230 : }
645 :
646 144 : void FlowMgmtManager::DeleteFlow(FlowEntryPtr &flow,
647 : const RevFlowDepParams ¶ms) {
648 : // Delete entries for flow from the tree
649 144 : FlowEntryInfo *old_info = FindFlowEntryInfo(flow);
650 144 : if (old_info == NULL)
651 0 : return;
652 :
653 144 : FlowMgmtKeyTree *old_tree = &old_info->tree_;
654 144 : assert(old_tree);
655 144 : old_info->count_++;
656 :
657 144 : FlowMgmtKeyTree::iterator old_it = old_tree->begin();
658 874 : while (old_it != old_tree->end()) {
659 730 : FlowMgmtKeyNode *node = old_it->second;
660 730 : DeleteFlowMgmtKey(flow.get(), old_info, old_it->first, node);
661 730 : FlowMgmtKeyTree::iterator tmp = old_it++;
662 730 : FlowMgmtKey *key = tmp->first;
663 730 : old_tree->erase(tmp);
664 730 : delete key;
665 730 : delete node;
666 : }
667 :
668 144 : assert(old_tree->size() == 0);
669 144 : DeleteFlowEntryInfo(flow);
670 : }
671 :
672 0 : void FlowMgmtManager::UpdateFlowStats(FlowEntryPtr &flow, uint32_t bytes,
673 : uint32_t packets, uint32_t oflow_bytes,
674 : const boost::uuids::uuid &u) {
675 : //Enqueue Flow Index Update Event request to flow-stats-collector
676 0 : agent_->flow_stats_manager()->UpdateStatsEvent(flow, bytes, packets,
677 : oflow_bytes, u);
678 0 : }
679 :
680 74 : bool FlowMgmtManager::HasVrfFlows(uint32_t vrf_id) {
681 74 : if (ip4_route_flow_mgmt_tree_.HasVrfFlows(vrf_id, Agent::INET4_UNICAST)) {
682 0 : return true;
683 : }
684 :
685 74 : if (ip6_route_flow_mgmt_tree_.HasVrfFlows(vrf_id, Agent::INET6_UNICAST)) {
686 0 : return true;
687 : }
688 :
689 74 : if (bridge_route_flow_mgmt_tree_.HasVrfFlows(vrf_id, Agent::BRIDGE)) {
690 0 : return true;
691 : }
692 :
693 74 : return false;
694 : }
695 :
696 0 : void FlowMgmtManager::VnFlowCounters(const VnEntry *vn, uint32_t *ingress_flow_count,
697 : uint32_t *egress_flow_count) {
698 0 : vn_flow_mgmt_tree_.VnFlowCounters(vn, ingress_flow_count,
699 : egress_flow_count);
700 0 : }
701 :
702 0 : void FlowMgmtManager::InterfaceFlowCount(const Interface *itf,
703 : uint64_t *created, uint64_t *aged,
704 : uint32_t *active_flows) {
705 0 : interface_flow_mgmt_tree_.InterfaceFlowCount(itf, created, aged,
706 : active_flows);
707 0 : }
708 :
709 : FlowEntryInfo *
710 374 : FlowMgmtManager::FindFlowEntryInfo(const FlowEntryPtr &flow) {
711 374 : return flow->flow_mgmt_info();
712 : }
713 :
714 : FlowEntryInfo *
715 230 : FlowMgmtManager::LocateFlowEntryInfo(FlowEntryPtr &flow) {
716 230 : FlowEntryInfo *info = FindFlowEntryInfo(flow);
717 230 : if (info != NULL)
718 86 : return info;
719 144 : info = new FlowEntryInfo(flow.get());
720 144 : flow->set_flow_mgmt_info(info);
721 144 : return info;
722 : }
723 :
724 : BgpAsAServiceFlowMgmtKey *
725 0 : FlowMgmtManager::FindBgpAsAServiceInfo(FlowEntry *flow,
726 : BgpAsAServiceFlowMgmtKey &key) {
727 0 : FlowEntryInfo *flow_info = FindFlowEntryInfo(flow);
728 0 : if (flow_info == NULL)
729 0 : return NULL;
730 :
731 0 : FlowMgmtKeyTree::iterator key_it = flow_info->tree_.find(&key);
732 0 : if (key_it == flow_info->tree().end())
733 0 : return NULL;
734 :
735 : BgpAsAServiceFlowMgmtKey *bkey =
736 0 : static_cast<BgpAsAServiceFlowMgmtKey *>(key_it->first);
737 0 : return bkey;
738 : }
739 :
740 144 : void FlowMgmtManager::DeleteFlowEntryInfo(FlowEntryPtr &flow) {
741 144 : FlowEntryInfo *info = flow->flow_mgmt_info();
742 144 : if (info == NULL)
743 0 : return;
744 :
745 144 : assert(info->tree_.size() == 0);
746 144 : flow->set_flow_mgmt_info(NULL);
747 144 : return;
748 : }
749 :
750 : /////////////////////////////////////////////////////////////////////////////
751 : // Routines to add/delete Flow and FlowMgmtKey in different trees
752 : /////////////////////////////////////////////////////////////////////////////
753 :
754 : // Add a FlowMgmtKey into FlowMgmtKeyTree for an object
755 : // The FlowMgmtKeyTree for object is passed as argument
756 1201 : void FlowMgmtManager::AddFlowMgmtKey(FlowEntry *flow, FlowEntryInfo *info,
757 : FlowMgmtKey *key, FlowMgmtKey *old_key) {
758 1201 : FlowMgmtKey *tmp = key->Clone();
759 1201 : FlowMgmtKeyNode *node = new FlowMgmtKeyNode(flow);
760 :
761 1201 : std::pair<FlowMgmtKeyTree::iterator, bool> ret = info->tree_.insert(
762 1201 : make_pair(tmp, node));
763 1201 : if (ret.second == false) {
764 403 : delete tmp;
765 403 : delete node;
766 403 : if (key->type() == FlowMgmtKey::ACL) {
767 : /* Copy the ACE Id list to existing key from new Key */
768 25 : FlowMgmtKey *existing_key = ret.first->first;
769 25 : AclFlowMgmtKey *akey = static_cast<AclFlowMgmtKey *>(existing_key);
770 25 : AclFlowMgmtKey *new_key = static_cast<AclFlowMgmtKey *>(key);
771 25 : akey->set_ace_id_list(new_key->ace_id_list());
772 : }
773 : }
774 :
775 1201 : switch (key->type()) {
776 228 : case FlowMgmtKey::INTERFACE:
777 228 : interface_flow_mgmt_tree_.Add(key, flow,
778 228 : (ret.second)? node : NULL);
779 228 : break;
780 :
781 33 : case FlowMgmtKey::ACL:
782 33 : acl_flow_mgmt_tree_.Add(key, flow, old_key,
783 33 : (ret.second)? node : NULL);
784 33 : break;
785 :
786 226 : case FlowMgmtKey::VN: {
787 226 : bool new_flow = vn_flow_mgmt_tree_.Add(key, flow,
788 226 : (ret.second)? node : NULL);
789 : VnFlowMgmtEntry *entry = static_cast<VnFlowMgmtEntry *>
790 226 : (vn_flow_mgmt_tree_.Find(key));
791 226 : entry->UpdateCounterOnAdd(flow, new_flow, info->local_flow_,
792 226 : info->ingress_);
793 226 : info->local_flow_ = flow->is_flags_set(FlowEntry::LocalFlow);
794 226 : info->ingress_ = flow->is_flags_set(FlowEntry::IngressDir);
795 226 : break;
796 : }
797 :
798 434 : case FlowMgmtKey::INET4:
799 434 : ip4_route_flow_mgmt_tree_.Add(key, flow,
800 434 : (ret.second)? node : NULL);
801 434 : break;
802 :
803 0 : case FlowMgmtKey::INET6:
804 0 : ip6_route_flow_mgmt_tree_.Add(key, flow,
805 0 : (ret.second)? node : NULL);
806 0 : break;
807 :
808 66 : case FlowMgmtKey::BRIDGE:
809 66 : bridge_route_flow_mgmt_tree_.Add(key, flow,
810 66 : (ret.second)? node : NULL);
811 66 : break;
812 :
813 214 : case FlowMgmtKey::NH:
814 214 : nh_flow_mgmt_tree_.Add(key, flow,
815 214 : (ret.second)? node : NULL);
816 214 : break;
817 :
818 0 : case FlowMgmtKey::BGPASASERVICE: {
819 0 : BgpAsAServiceFlowMgmtKey *bgp_service_key =
820 : static_cast<BgpAsAServiceFlowMgmtKey *>(key);
821 0 : int cn_index = bgp_service_key->cn_index();
822 0 : if (cn_index != BgpAsAServiceFlowMgmtTree::kInvalidCnIndex) {
823 0 : bgp_as_a_service_flow_mgmt_tree_[cn_index].get()->Add(key, flow,
824 0 : (ret.second)? node : NULL);
825 : boost::uuids::uuid hc_uuid;
826 0 : if (agent()->oper_db()->bgp_as_a_service()->GetBgpHealthCheck(
827 0 : static_cast<const VmInterface *>(flow->intf_entry()), &hc_uuid)) {
828 0 : FlowMgmtKey *inserted_key = ret.first->first;
829 0 : BgpAsAServiceFlowMgmtKey *bkey =
830 : static_cast<BgpAsAServiceFlowMgmtKey *>(inserted_key);
831 0 : bkey->StartHealthCheck(agent(), flow, hc_uuid);
832 : }
833 : }
834 0 : break;
835 : }
836 :
837 0 : default:
838 0 : assert(0);
839 : }
840 1201 : }
841 :
842 : // Delete a FlowMgmtKey from FlowMgmtKeyTree for an object
843 : // The FlowMgmtKeyTree for object is passed as argument
844 798 : void FlowMgmtManager::DeleteFlowMgmtKey(
845 : FlowEntry *flow, FlowEntryInfo *info, FlowMgmtKey *key,
846 : FlowMgmtKeyNode *node) {
847 :
848 798 : FlowMgmtKeyTree::iterator it = info->tree_.find(key);
849 798 : assert(it != info->tree_.end());
850 :
851 798 : switch (key->type()) {
852 144 : case FlowMgmtKey::INTERFACE:
853 144 : interface_flow_mgmt_tree_.Delete(key, flow, node);
854 144 : break;
855 :
856 8 : case FlowMgmtKey::ACL:
857 8 : acl_flow_mgmt_tree_.Delete(key, flow, node);
858 8 : break;
859 :
860 142 : case FlowMgmtKey::VN: {
861 142 : vn_flow_mgmt_tree_.Delete(key, flow, node);
862 : VnFlowMgmtEntry *entry = static_cast<VnFlowMgmtEntry *>
863 142 : (vn_flow_mgmt_tree_.Find(key));
864 142 : if (entry)
865 142 : entry->UpdateCounterOnDel(flow, info->local_flow_, info->ingress_);
866 142 : info->local_flow_ = flow->is_flags_set(FlowEntry::LocalFlow);
867 142 : info->ingress_ = flow->is_flags_set(FlowEntry::IngressDir);
868 142 : break;
869 : }
870 :
871 322 : case FlowMgmtKey::INET4:
872 322 : ip4_route_flow_mgmt_tree_.Delete(key, flow, node);
873 322 : break;
874 :
875 0 : case FlowMgmtKey::INET6:
876 0 : ip6_route_flow_mgmt_tree_.Delete(key, flow, node);
877 0 : break;
878 :
879 32 : case FlowMgmtKey::BRIDGE:
880 32 : bridge_route_flow_mgmt_tree_.Delete(key, flow, node);
881 32 : break;
882 :
883 150 : case FlowMgmtKey::NH:
884 150 : nh_flow_mgmt_tree_.Delete(key, flow, node);
885 150 : break;
886 :
887 0 : case FlowMgmtKey::BGPASASERVICE: {
888 : BgpAsAServiceFlowMgmtKey *bkey =
889 0 : static_cast<BgpAsAServiceFlowMgmtKey *>(it->first);
890 0 : bkey->StopHealthCheck(flow);
891 0 : BgpAsAServiceFlowMgmtKey *bgp_service_key =
892 : static_cast<BgpAsAServiceFlowMgmtKey *>(key);
893 0 : uint8_t count = bgp_service_key->cn_index();
894 0 : bgp_as_a_service_flow_mgmt_tree_[count].get()->Delete(key, flow, node);
895 0 : break;
896 : }
897 :
898 0 : default:
899 0 : assert(0);
900 : }
901 798 : }
|