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