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 1 : FlowMgmtManager::FlowMgmtManager(Agent *agent, uint16_t table_index) :
22 1 : agent_(agent),
23 1 : table_index_(table_index),
24 1 : acl_flow_mgmt_tree_(this),
25 1 : interface_flow_mgmt_tree_(this),
26 1 : vn_flow_mgmt_tree_(this),
27 1 : ip4_route_flow_mgmt_tree_(this),
28 1 : ip6_route_flow_mgmt_tree_(this),
29 1 : bridge_route_flow_mgmt_tree_(this),
30 1 : vrf_flow_mgmt_tree_(this),
31 1 : nh_flow_mgmt_tree_(this),
32 1 : flow_mgmt_dbclient_(new FlowMgmtDbClient(agent, this)),
33 1 : request_queue_(agent_->task_scheduler()->GetTaskId(kTaskFlowMgmt),
34 : table_index,
35 : boost::bind(&FlowMgmtManager::RequestHandler, this, _1)),
36 1 : db_event_queue_(agent_->task_scheduler()->GetTaskId(kTaskFlowMgmt),
37 : table_index,
38 : boost::bind(&FlowMgmtManager::DBRequestHandler, this, _1),
39 4 : db_event_queue_.kMaxSize, 1) {
40 1 : request_queue_.set_name("Flow management");
41 1 : request_queue_.set_measure_busy_time(agent->MeasureQueueDelay());
42 1 : db_event_queue_.set_name("Flow DB Event Queue");
43 3 : for (uint8_t count = 0; count < MAX_XMPP_SERVERS; count++) {
44 2 : bgp_as_a_service_flow_mgmt_tree_[count].reset(
45 2 : new BgpAsAServiceFlowMgmtTree(this, count));
46 : }
47 1 : }
48 :
49 1 : void FlowMgmtManager::Init() {
50 1 : flow_mgmt_dbclient_->Init();
51 1 : agent_->acl_table()->set_ace_flow_sandesh_data_cb
52 1 : (boost::bind(&FlowMgmtManager::SetAceSandeshData, this, _1, _2, _3));
53 1 : agent_->acl_table()->set_acl_flow_sandesh_data_cb
54 1 : (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 1 : 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 1 : 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 1 : agent_->controller()->RegisterControllerChangeCallback(boost::bind
66 : (&FlowMgmtManager::ControllerNotify, this, _1));
67 1 : }
68 :
69 1 : void FlowMgmtManager::Shutdown() {
70 1 : request_queue_.Shutdown();
71 1 : db_event_queue_.Shutdown();
72 1 : flow_mgmt_dbclient_->Shutdown();
73 1 : }
74 :
75 1 : void FlowMgmtManager::InitLogQueue(Agent *agent) {
76 1 : uint32_t task_id = agent->task_scheduler()->GetTaskId(kTaskFlowLogging);
77 2 : log_queue_ = new FlowMgmtQueue(task_id, 0,
78 : boost::bind(&FlowMgmtManager::LogHandler,
79 1 : _1));
80 1 : log_queue_->set_name("Flow Log Queue");
81 1 : log_queue_->SetBounded(true);
82 1 : }
83 :
84 1 : void FlowMgmtManager::ShutdownLogQueue() {
85 1 : log_queue_->Shutdown();
86 1 : delete log_queue_;
87 1 : }
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 2 : void FlowMgmtManager::ControllerNotify(uint8_t index) {
112 2 : FlowMgmtRequestPtr req(new BgpAsAServiceFlowMgmtRequest(index));
113 2 : request_queue_.Enqueue(req);
114 2 : }
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 100 : 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 100 : FlowMgmtRequest *req = flow->flow_mgmt_request();
152 100 : if (req == NULL) {
153 50 : req = new FlowMgmtRequest(FlowMgmtRequest::UPDATE_FLOW, flow);
154 50 : flow->set_flow_mgmt_request(req);
155 50 : request_queue_.Enqueue(FlowMgmtRequestPtr(req));
156 : }
157 100 : }
158 :
159 94 : 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 94 : FlowMgmtRequest *req = flow->flow_mgmt_request();
165 94 : if (req == NULL) {
166 94 : req = new FlowMgmtRequest(FlowMgmtRequest::UPDATE_FLOW, flow);
167 94 : flow->set_flow_mgmt_request(req);
168 94 : request_queue_.Enqueue(FlowMgmtRequestPtr(req));
169 : }
170 :
171 94 : req->set_params(params);
172 94 : }
173 :
174 0 : void FlowMgmtManager::FlowStatsUpdateEvent(FlowEntry *flow, uint32_t bytes,
175 : uint32_t packets,
176 : uint32_t oflow_bytes,
177 : const boost::uuids::uuid &u) {
178 0 : if (bytes == 0 && packets == 0 && oflow_bytes == 0) {
179 0 : 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 24 : void FlowMgmtManager::RetryVrfDeleteEvent(const VrfEntry *vrf) {
193 : FlowMgmtRequestPtr req(new FlowMgmtRequest
194 24 : (FlowMgmtRequest::RETRY_DELETE_VRF, vrf, 0));
195 24 : request_queue_.Enqueue(req);
196 24 : }
197 :
198 0 : void FlowMgmtManager::DummyEvent() {
199 0 : FlowMgmtRequestPtr req(new FlowMgmtRequest(FlowMgmtRequest::DUMMY));
200 0 : request_queue_.Enqueue(req);
201 0 : }
202 :
203 408 : void FlowMgmtManager::AddDBEntryEvent(const DBEntry *entry, uint32_t gen_id) {
204 : FlowMgmtRequestPtr req(new FlowMgmtRequest(FlowMgmtRequest::ADD_DBENTRY,
205 408 : entry, gen_id));
206 408 : db_event_queue_.Enqueue(req);
207 408 : }
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 288 : void FlowMgmtManager::DeleteDBEntryEvent(const DBEntry *entry,
217 : uint32_t gen_id) {
218 : FlowMgmtRequestPtr req(new FlowMgmtRequest(FlowMgmtRequest::DELETE_DBENTRY,
219 288 : entry, gen_id));
220 288 : db_event_queue_.Enqueue(req);
221 288 : }
222 :
223 0 : void FlowMgmtManager::RouteNHChangeEvent(const DBEntry *entry,
224 : uint32_t gen_id) {
225 : FlowMgmtRequestPtr req(new FlowMgmtRequest
226 : (FlowMgmtRequest::DELETE_LAYER2_FLOW,
227 0 : entry, gen_id));
228 0 : db_event_queue_.Enqueue(req);
229 0 : }
230 :
231 426 : void FlowMgmtManager::EnqueueFlowEvent(FlowEvent *event) {
232 426 : agent_->pkt()->get_flow_proto()->EnqueueFlowEvent(event);
233 426 : }
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 144 : void FlowMgmtManager::DBEntryEvent(FlowEvent::Event event, FlowMgmtKey *key,
244 : FlowEntry *flow) {
245 144 : FlowEvent *flow_resp = new FlowEvent(event, NULL, key->db_entry());
246 144 : key->KeyToFlowRequest(flow_resp);
247 144 : flow_resp->set_flow(flow);
248 144 : EnqueueFlowEvent(flow_resp);
249 144 : }
250 :
251 282 : void FlowMgmtManager::FreeDBEntryEvent(FlowEvent::Event event, FlowMgmtKey *key,
252 : uint32_t gen_id) {
253 282 : FlowEvent *flow_resp = new FlowEvent(event, table_index_, key->db_entry(),
254 282 : gen_id);
255 282 : EnqueueFlowEvent(flow_resp);
256 282 : }
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 707 : bool FlowMgmtManager::ProcessEvent(FlowMgmtRequest *req, FlowMgmtKey *key,
274 : FlowMgmtTree *tree) {
275 707 : InetRouteFlowMgmtTree* itree = dynamic_cast<InetRouteFlowMgmtTree*>(tree);
276 707 : switch (req->event()) {
277 408 : case FlowMgmtRequest::ADD_DBENTRY:
278 408 : tree->OperEntryAdd(req, key);
279 408 : break;
280 :
281 11 : case FlowMgmtRequest::CHANGE_DBENTRY:
282 11 : tree->OperEntryChange(req, key);
283 11 : break;
284 :
285 288 : case FlowMgmtRequest::DELETE_DBENTRY:
286 : case FlowMgmtRequest::IMPLICIT_ROUTE_DELETE:
287 288 : tree->OperEntryDelete(req, key);
288 288 : break;
289 :
290 0 : case FlowMgmtRequest::DELETE_LAYER2_FLOW:
291 0 : assert(itree);
292 0 : itree->RouteNHChangeEvent(req, key);
293 0 : break;
294 :
295 0 : default:
296 0 : assert(0);
297 : break;
298 : }
299 :
300 707 : return true;
301 : }
302 :
303 707 : bool FlowMgmtManager::DBRequestHandler(FlowMgmtRequest *req,
304 : const DBEntry *entry) {
305 707 : const Interface *intf = dynamic_cast<const Interface *>(entry);
306 707 : if (intf) {
307 68 : InterfaceFlowMgmtKey key(intf);
308 68 : return ProcessEvent(req, &key, &interface_flow_mgmt_tree_);
309 68 : }
310 :
311 639 : const VnEntry *vn = dynamic_cast<const VnEntry *>(entry);
312 639 : if (vn) {
313 12 : VnFlowMgmtKey key(vn);
314 12 : return ProcessEvent(req, &key, &vn_flow_mgmt_tree_);
315 12 : }
316 :
317 627 : const AclDBEntry *acl = dynamic_cast<const AclDBEntry *>(entry);
318 627 : if (acl) {
319 10 : AclFlowMgmtKey key(acl, NULL);
320 10 : return ProcessEvent(req, &key, &acl_flow_mgmt_tree_);
321 10 : }
322 :
323 617 : const NextHop *nh = dynamic_cast<const NextHop *>(entry);
324 617 : if (nh) {
325 260 : NhFlowMgmtKey key(static_cast<const NextHop *>(req->db_entry()));
326 260 : return ProcessEvent(req, &key, &nh_flow_mgmt_tree_);
327 260 : }
328 :
329 : const InetUnicastRouteEntry *inet_uc_rt =
330 357 : dynamic_cast<const InetUnicastRouteEntry *>(entry);
331 357 : if (inet_uc_rt) {
332 192 : InetRouteFlowMgmtKey key(inet_uc_rt);
333 192 : if (inet_uc_rt->prefix_address().is_v4()) {
334 126 : return ProcessEvent(req, &key, &ip4_route_flow_mgmt_tree_);
335 : }
336 66 : if (inet_uc_rt->prefix_address().is_v6()) {
337 66 : return ProcessEvent(req, &key, &ip6_route_flow_mgmt_tree_);
338 : }
339 192 : }
340 :
341 : const BridgeRouteEntry *bridge =
342 165 : dynamic_cast<const BridgeRouteEntry *>(entry);
343 165 : if (bridge) {
344 143 : BridgeRouteFlowMgmtKey key(bridge);
345 143 : return ProcessEvent(req, &key, &bridge_route_flow_mgmt_tree_);
346 143 : }
347 :
348 22 : const VrfEntry *vrf = dynamic_cast<const VrfEntry *>(entry);
349 22 : if (vrf) {
350 22 : VrfFlowMgmtKey key(vrf);
351 22 : return ProcessEvent(req, &key, &vrf_flow_mgmt_tree_);
352 22 : }
353 :
354 0 : assert(0);
355 : return true;
356 : }
357 :
358 : bool
359 2 : FlowMgmtManager::BgpAsAServiceRequestHandler(FlowMgmtRequest *req) {
360 :
361 : BgpAsAServiceFlowMgmtRequest *bgp_as_a_service_request =
362 2 : dynamic_cast<BgpAsAServiceFlowMgmtRequest *>(req);
363 2 : 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 2 : } else if (bgp_as_a_service_request->type() ==
373 : BgpAsAServiceFlowMgmtRequest::CONTROLLER) {
374 2 : bgp_as_a_service_flow_mgmt_tree_[bgp_as_a_service_request->index()].get()->
375 2 : 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 2 : return true;
391 : }
392 :
393 170 : bool FlowMgmtManager::RequestHandler(FlowMgmtRequestPtr req) {
394 170 : switch (req->event()) {
395 144 : case FlowMgmtRequest::UPDATE_FLOW: {
396 144 : 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 144 : std::scoped_lock mutex(flow->mutex());
401 144 : flow->set_flow_mgmt_request(NULL);
402 :
403 : // Update flow-mgmt information based on flow-state
404 144 : if (flow->deleted() == false) {
405 : FlowMgmtRequestPtr log_req(new FlowMgmtRequest
406 : (FlowMgmtRequest::ADD_FLOW,
407 100 : req->flow().get()));
408 100 : log_queue_->Enqueue(log_req);
409 :
410 : //Enqueue Add request to flow-stats-collector
411 100 : agent_->flow_stats_manager()->AddEvent(req->flow());
412 :
413 : //Enqueue Add request to UVE module for ACE stats
414 100 : EnqueueUveAddEvent(flow);
415 :
416 100 : AddFlow(req->flow());
417 :
418 100 : } else {
419 : FlowMgmtRequestPtr log_req(new FlowMgmtRequest
420 : (FlowMgmtRequest::DELETE_FLOW,
421 44 : req->flow().get(), req->params()));
422 44 : log_queue_->Enqueue(log_req);
423 :
424 : //Enqueue Delete request to flow-stats-collector
425 44 : agent_->flow_stats_manager()->DeleteEvent(flow, req->params());
426 :
427 : //Enqueue Delete request to UVE module for ACE stats
428 44 : EnqueueUveDeleteEvent(flow);
429 :
430 44 : DeleteFlow(req->flow(), req->params());
431 44 : }
432 144 : break;
433 144 : }
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 24 : case FlowMgmtRequest::RETRY_DELETE_VRF: {
443 24 : RetryVrfDelete(req->vrf_id());
444 24 : break;
445 : }
446 :
447 2 : case FlowMgmtRequest::DELETE_BGP_AAS_FLOWS: {
448 2 : BgpAsAServiceRequestHandler(req.get());
449 2 : break;
450 : }
451 :
452 0 : case FlowMgmtRequest::DUMMY:
453 0 : break;
454 :
455 0 : default:
456 0 : assert(0);
457 :
458 : }
459 :
460 170 : return true;
461 : }
462 :
463 707 : bool FlowMgmtManager::DBRequestHandler(FlowMgmtRequestPtr req) {
464 707 : switch (req->event()) {
465 707 : case FlowMgmtRequest::ADD_DBENTRY:
466 : case FlowMgmtRequest::CHANGE_DBENTRY:
467 : case FlowMgmtRequest::DELETE_DBENTRY:
468 : case FlowMgmtRequest::DELETE_LAYER2_FLOW: {
469 707 : DBRequestHandler(req.get(), req->db_entry());
470 707 : break;
471 : }
472 :
473 0 : default:
474 0 : assert(0);
475 :
476 : }
477 :
478 707 : return true;
479 : }
480 :
481 144 : bool FlowMgmtManager::LogHandler(FlowMgmtRequestPtr req) {
482 144 : FlowEntry *flow = req->flow().get();
483 144 : FlowEntry *rflow = flow->reverse_flow_entry();
484 :
485 188 : FLOW_LOCK(flow, rflow, FlowEvent::FLOW_MESSAGE);
486 144 : switch (req->event()) {
487 100 : case FlowMgmtRequest::ADD_FLOW: {
488 100 : LogFlowUnlocked(flow, "ADD");
489 100 : break;
490 : }
491 :
492 44 : case FlowMgmtRequest::DELETE_FLOW: {
493 44 : LogFlowUnlocked(flow, "DEL");
494 44 : break;
495 : }
496 :
497 0 : default:
498 0 : assert(0);
499 :
500 : }
501 :
502 144 : return true;
503 144 : }
504 :
505 201 : void FlowMgmtManager::RetryVrfDelete(uint32_t vrf_id) {
506 201 : vrf_flow_mgmt_tree_.RetryDelete(vrf_id);
507 201 : }
508 :
509 : // Extract all the FlowMgmtKey for a flow
510 144 : void FlowMgmtManager::LogFlowUnlocked(FlowEntry *flow, const std::string &op) {
511 144 : if (flow->trace() == false)
512 70 : return;
513 74 : FlowInfo trace;
514 74 : flow->FillFlowInfo(trace);
515 74 : FLOW_TRACE(Trace, op, trace);
516 74 : }
517 :
518 : // Extract all the FlowMgmtKey for a flow
519 100 : void FlowMgmtManager::MakeFlowMgmtKeyTree(FlowEntry *flow,
520 : FlowMgmtKeyTree *tree) {
521 100 : acl_flow_mgmt_tree_.ExtractKeys(flow, tree);
522 100 : interface_flow_mgmt_tree_.ExtractKeys(flow, tree);
523 100 : vn_flow_mgmt_tree_.ExtractKeys(flow, tree);
524 100 : ip4_route_flow_mgmt_tree_.ExtractKeys(flow, tree);
525 100 : ip6_route_flow_mgmt_tree_.ExtractKeys(flow, tree);
526 100 : bridge_route_flow_mgmt_tree_.ExtractKeys(flow, tree);
527 100 : nh_flow_mgmt_tree_.ExtractKeys(flow, tree);
528 100 : 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 100 : }
536 :
537 100 : void FlowMgmtManager::EnqueueUveAddEvent(const FlowEntry *flow) const {
538 100 : AgentUveStats *uve = dynamic_cast<AgentUveStats *>(agent_->uve());
539 100 : if (uve) {
540 100 : const Interface *itf = flow->intf_entry();
541 100 : const VmInterface *vmi = dynamic_cast<const VmInterface *>(itf);
542 100 : const VnEntry *vn = flow->vn_entry();
543 100 : string vn_name = vn? vn->GetName() : "";
544 100 : string itf_name = vmi? vmi->cfg_name() : "";
545 100 : FlowUveVnAcePolicyInfo vn_ace_info;
546 100 : FlowUveFwPolicyInfo fw_policy_info;
547 :
548 100 : flow->FillUveVnAceInfo(&vn_ace_info);
549 100 : if (!itf_name.empty()) {
550 100 : flow->FillUveFwStatsInfo(&fw_policy_info, true);
551 : }
552 : boost::shared_ptr<FlowUveStatsRequest> req(new FlowUveStatsRequest
553 100 : (FlowUveStatsRequest::ADD_FLOW, flow->uuid(), itf_name,
554 100 : flow->sg_rule_uuid(), vn_ace_info, fw_policy_info));
555 :
556 100 : if (!req->sg_info_valid() && !req->vn_ace_valid() &&
557 0 : !req->fw_policy_valid()) {
558 0 : return;
559 : }
560 :
561 100 : uve->stats_manager()->EnqueueEvent(req);
562 100 : }
563 : }
564 :
565 44 : void FlowMgmtManager::EnqueueUveDeleteEvent(const FlowEntry *flow) const {
566 44 : AgentUveStats *uve = dynamic_cast<AgentUveStats *>(agent_->uve());
567 44 : if (uve) {
568 44 : const Interface *itf = flow->intf_entry();
569 44 : const VmInterface *vmi = dynamic_cast<const VmInterface *>(itf);
570 44 : string itf_name = vmi? vmi->cfg_name() : "";
571 44 : FlowUveFwPolicyInfo fw_policy_info;
572 44 : if (!itf_name.empty()) {
573 7 : flow->FillUveFwStatsInfo(&fw_policy_info, false);
574 : }
575 : boost::shared_ptr<FlowUveStatsRequest> req(new FlowUveStatsRequest
576 44 : (FlowUveStatsRequest::DELETE_FLOW, flow->uuid(), itf_name,
577 44 : fw_policy_info));
578 44 : uve->stats_manager()->EnqueueEvent(req);
579 44 : }
580 44 : }
581 :
582 100 : void FlowMgmtManager::AddFlow(FlowEntryPtr &flow) {
583 100 : FlowMgmtKeyTree new_tree;
584 100 : MakeFlowMgmtKeyTree(flow.get(), &new_tree);
585 :
586 : // Get old FlowMgmtKeyTree
587 100 : FlowEntryInfo *old_info = LocateFlowEntryInfo(flow);
588 100 : FlowMgmtKeyTree *old_tree = &old_info->tree_;
589 100 : assert(old_tree);
590 100 : old_info->count_++;
591 :
592 : // Apply the difference in old and new key tree
593 100 : FlowMgmtKeyTree::iterator new_it = new_tree.begin();
594 100 : FlowMgmtKeyTree::iterator old_it = old_tree->begin();
595 :
596 398 : while (new_it != new_tree.end() && old_it != old_tree->end()) {
597 298 : FlowMgmtKey *new_key = new_it->first;
598 298 : FlowMgmtKey *old_key = old_it->first;
599 298 : if (new_key->IsLess(old_key)) {
600 6 : AddFlowMgmtKey(flow.get(), old_info, new_key, NULL);
601 6 : new_it++;
602 292 : } else if (old_key->IsLess(new_key)) {
603 20 : FlowMgmtKeyNode *node = old_it->second;
604 20 : DeleteFlowMgmtKey(flow.get(), old_info, old_key,
605 : node);
606 20 : FlowMgmtKeyTree::iterator tmp = old_it++;
607 20 : FlowMgmtKey *key = tmp->first;
608 20 : old_tree->erase(tmp);
609 20 : delete key;
610 20 : delete node;
611 : } else {
612 272 : AddFlowMgmtKey(flow.get(), old_info, new_key, old_key);
613 272 : old_it++;
614 272 : new_it++;
615 : }
616 : }
617 :
618 307 : while (new_it != new_tree.end()) {
619 207 : FlowMgmtKey *new_key = new_it->first;
620 207 : AddFlowMgmtKey(flow.get(), old_info, new_key, NULL);
621 207 : new_it++;
622 : }
623 :
624 113 : while (old_it != old_tree->end()) {
625 13 : FlowMgmtKey *old_key = old_it->first;
626 13 : FlowMgmtKeyNode *node = old_it->second;
627 13 : DeleteFlowMgmtKey(flow.get(), old_info, old_key, node);
628 13 : FlowMgmtKeyTree::iterator tmp = old_it++;
629 13 : FlowMgmtKey *key = tmp->first;
630 13 : old_tree->erase(tmp);
631 13 : delete key;
632 13 : delete node;
633 : }
634 :
635 100 : new_it = new_tree.begin();
636 585 : while (new_it != new_tree.end()) {
637 485 : FlowMgmtKeyTree::iterator tmp = new_it++;
638 485 : FlowMgmtKey *key = tmp->first;
639 485 : FlowMgmtKeyNode *node = tmp->second;
640 485 : new_tree.erase(tmp);
641 485 : delete key;
642 485 : delete node;
643 : }
644 100 : }
645 :
646 44 : void FlowMgmtManager::DeleteFlow(FlowEntryPtr &flow,
647 : const RevFlowDepParams ¶ms) {
648 : // Delete entries for flow from the tree
649 44 : FlowEntryInfo *old_info = FindFlowEntryInfo(flow);
650 44 : if (old_info == NULL)
651 0 : return;
652 :
653 44 : FlowMgmtKeyTree *old_tree = &old_info->tree_;
654 44 : assert(old_tree);
655 44 : old_info->count_++;
656 :
657 44 : FlowMgmtKeyTree::iterator old_it = old_tree->begin();
658 224 : while (old_it != old_tree->end()) {
659 180 : FlowMgmtKeyNode *node = old_it->second;
660 180 : DeleteFlowMgmtKey(flow.get(), old_info, old_it->first, node);
661 180 : FlowMgmtKeyTree::iterator tmp = old_it++;
662 180 : FlowMgmtKey *key = tmp->first;
663 180 : old_tree->erase(tmp);
664 180 : delete key;
665 180 : delete node;
666 : }
667 :
668 44 : assert(old_tree->size() == 0);
669 44 : 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 8 : bool FlowMgmtManager::HasVrfFlows(uint32_t vrf_id) {
681 8 : if (ip4_route_flow_mgmt_tree_.HasVrfFlows(vrf_id, Agent::INET4_UNICAST)) {
682 0 : return true;
683 : }
684 :
685 8 : if (ip6_route_flow_mgmt_tree_.HasVrfFlows(vrf_id, Agent::INET6_UNICAST)) {
686 0 : return true;
687 : }
688 :
689 8 : if (bridge_route_flow_mgmt_tree_.HasVrfFlows(vrf_id, Agent::BRIDGE)) {
690 0 : return true;
691 : }
692 :
693 8 : 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 144 : FlowMgmtManager::FindFlowEntryInfo(const FlowEntryPtr &flow) {
711 144 : return flow->flow_mgmt_info();
712 : }
713 :
714 : FlowEntryInfo *
715 100 : FlowMgmtManager::LocateFlowEntryInfo(FlowEntryPtr &flow) {
716 100 : FlowEntryInfo *info = FindFlowEntryInfo(flow);
717 100 : if (info != NULL)
718 56 : return info;
719 44 : info = new FlowEntryInfo(flow.get());
720 44 : flow->set_flow_mgmt_info(info);
721 44 : 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 44 : void FlowMgmtManager::DeleteFlowEntryInfo(FlowEntryPtr &flow) {
741 44 : FlowEntryInfo *info = flow->flow_mgmt_info();
742 44 : if (info == NULL)
743 0 : return;
744 :
745 44 : assert(info->tree_.size() == 0);
746 44 : flow->set_flow_mgmt_info(NULL);
747 44 : 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 485 : void FlowMgmtManager::AddFlowMgmtKey(FlowEntry *flow, FlowEntryInfo *info,
757 : FlowMgmtKey *key, FlowMgmtKey *old_key) {
758 485 : FlowMgmtKey *tmp = key->Clone();
759 485 : FlowMgmtKeyNode *node = new FlowMgmtKeyNode(flow);
760 :
761 485 : std::pair<FlowMgmtKeyTree::iterator, bool> ret = info->tree_.insert(
762 485 : make_pair(tmp, node));
763 485 : if (ret.second == false) {
764 272 : delete tmp;
765 272 : delete node;
766 272 : 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 485 : switch (key->type()) {
776 100 : case FlowMgmtKey::INTERFACE:
777 100 : interface_flow_mgmt_tree_.Add(key, flow,
778 100 : (ret.second)? node : NULL);
779 100 : break;
780 :
781 32 : case FlowMgmtKey::ACL:
782 32 : acl_flow_mgmt_tree_.Add(key, flow, old_key,
783 32 : (ret.second)? node : NULL);
784 32 : break;
785 :
786 100 : case FlowMgmtKey::VN: {
787 100 : bool new_flow = vn_flow_mgmt_tree_.Add(key, flow,
788 100 : (ret.second)? node : NULL);
789 : VnFlowMgmtEntry *entry = static_cast<VnFlowMgmtEntry *>
790 100 : (vn_flow_mgmt_tree_.Find(key));
791 100 : entry->UpdateCounterOnAdd(flow, new_flow, info->local_flow_,
792 100 : info->ingress_);
793 100 : info->local_flow_ = flow->is_flags_set(FlowEntry::LocalFlow);
794 100 : info->ingress_ = flow->is_flags_set(FlowEntry::IngressDir);
795 100 : break;
796 : }
797 :
798 101 : case FlowMgmtKey::INET4:
799 101 : ip4_route_flow_mgmt_tree_.Add(key, flow,
800 101 : (ret.second)? node : NULL);
801 101 : 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 62 : case FlowMgmtKey::BRIDGE:
809 62 : bridge_route_flow_mgmt_tree_.Add(key, flow,
810 62 : (ret.second)? node : NULL);
811 62 : break;
812 :
813 90 : case FlowMgmtKey::NH:
814 90 : nh_flow_mgmt_tree_.Add(key, flow,
815 90 : (ret.second)? node : NULL);
816 90 : 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 485 : }
841 :
842 : // Delete a FlowMgmtKey from FlowMgmtKeyTree for an object
843 : // The FlowMgmtKeyTree for object is passed as argument
844 213 : void FlowMgmtManager::DeleteFlowMgmtKey(
845 : FlowEntry *flow, FlowEntryInfo *info, FlowMgmtKey *key,
846 : FlowMgmtKeyNode *node) {
847 :
848 213 : FlowMgmtKeyTree::iterator it = info->tree_.find(key);
849 213 : assert(it != info->tree_.end());
850 :
851 213 : switch (key->type()) {
852 44 : case FlowMgmtKey::INTERFACE:
853 44 : interface_flow_mgmt_tree_.Delete(key, flow, node);
854 44 : break;
855 :
856 7 : case FlowMgmtKey::ACL:
857 7 : acl_flow_mgmt_tree_.Delete(key, flow, node);
858 7 : break;
859 :
860 44 : case FlowMgmtKey::VN: {
861 44 : vn_flow_mgmt_tree_.Delete(key, flow, node);
862 : VnFlowMgmtEntry *entry = static_cast<VnFlowMgmtEntry *>
863 44 : (vn_flow_mgmt_tree_.Find(key));
864 44 : if (entry)
865 44 : entry->UpdateCounterOnDel(flow, info->local_flow_, info->ingress_);
866 44 : info->local_flow_ = flow->is_flags_set(FlowEntry::LocalFlow);
867 44 : info->ingress_ = flow->is_flags_set(FlowEntry::IngressDir);
868 44 : break;
869 : }
870 :
871 44 : case FlowMgmtKey::INET4:
872 44 : ip4_route_flow_mgmt_tree_.Delete(key, flow, node);
873 44 : break;
874 :
875 0 : case FlowMgmtKey::INET6:
876 0 : ip6_route_flow_mgmt_tree_.Delete(key, flow, node);
877 0 : break;
878 :
879 28 : case FlowMgmtKey::BRIDGE:
880 28 : bridge_route_flow_mgmt_tree_.Delete(key, flow, node);
881 28 : break;
882 :
883 46 : case FlowMgmtKey::NH:
884 46 : nh_flow_mgmt_tree_.Delete(key, flow, node);
885 46 : 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 213 : }
|