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