Line data Source code
1 : #include "pkt/flow_mgmt/flow_mgmt_dbclient.h"
2 : #include "pkt/flow_mgmt.h"
3 : #include "oper/ecmp_load_balance.h"
4 : #include "oper/ecmp.h"
5 : #include <oper/tunnel_nh.h>
6 :
7 3 : void FlowMgmtDbClient::Init() {
8 3 : acl_listener_id_ = agent_->acl_table()->Register
9 3 : (boost::bind(&FlowMgmtDbClient::AclNotify, this, _1, _2));
10 :
11 3 : interface_listener_id_ = agent_->interface_table()->Register
12 3 : (boost::bind(&FlowMgmtDbClient::InterfaceNotify, this, _1, _2));
13 :
14 3 : vn_listener_id_ = agent_->vn_table()->Register
15 3 : (boost::bind(&FlowMgmtDbClient::VnNotify, this, _1, _2));
16 :
17 3 : vrf_listener_id_ = agent_->vrf_table()->Register
18 3 : (boost::bind(&FlowMgmtDbClient::VrfNotify, this, _1, _2));
19 :
20 3 : nh_listener_id_ = agent_->nexthop_table()->Register
21 3 : (boost::bind(&FlowMgmtDbClient::NhNotify, this, _1, _2));
22 3 : return;
23 : }
24 :
25 3 : void FlowMgmtDbClient::Shutdown() {
26 3 : agent_->acl_table()->Unregister(acl_listener_id_);
27 3 : agent_->interface_table()->Unregister(interface_listener_id_);
28 3 : agent_->vn_table()->Unregister(vn_listener_id_);
29 3 : agent_->vm_table()->Unregister(vm_listener_id_);
30 3 : agent_->vrf_table()->Unregister(vrf_listener_id_);
31 3 : agent_->nexthop_table()->Unregister(nh_listener_id_);
32 3 : }
33 :
34 3 : FlowMgmtDbClient::FlowMgmtDbClient(Agent *agent, FlowMgmtManager *mgr) :
35 3 : agent_(agent),
36 3 : mgr_(mgr),
37 3 : acl_listener_id_(),
38 3 : interface_listener_id_(),
39 3 : vn_listener_id_(),
40 3 : vm_listener_id_(),
41 3 : vrf_listener_id_(),
42 3 : nh_listener_id_() {
43 3 : }
44 :
45 6 : FlowMgmtDbClient::~FlowMgmtDbClient() {
46 6 : }
47 :
48 1122 : void FlowMgmtDbClient::AddEvent(const DBEntry *entry, FlowMgmtState *state) {
49 1122 : mgr_->AddDBEntryEvent(entry, state->gen_id_);
50 1122 : }
51 :
52 812 : void FlowMgmtDbClient::DeleteEvent(const DBEntry *entry, FlowMgmtState *state) {
53 812 : state->gen_id_++;
54 812 : state->deleted_ = true;
55 812 : mgr_->DeleteDBEntryEvent(entry, state->gen_id_);
56 812 : }
57 :
58 44 : void FlowMgmtDbClient::DeleteAllFlow(const DBEntry *entry,
59 : FlowMgmtState *state) {
60 44 : mgr_->DeleteDBEntryEvent(entry, state->gen_id_);
61 44 : }
62 :
63 11 : void FlowMgmtDbClient::ChangeEvent(const DBEntry *entry, FlowMgmtState *state) {
64 11 : mgr_->ChangeDBEntryEvent(entry, state->gen_id_);
65 11 : }
66 :
67 0 : void FlowMgmtDbClient::RouteNHChangeEvent(const DBEntry *entry,
68 : FlowMgmtState *state) {
69 0 : mgr_->RouteNHChangeEvent(entry, state->gen_id_);
70 0 : }
71 :
72 : ////////////////////////////////////////////////////////////////////////////
73 : // Interface notification handler
74 : ////////////////////////////////////////////////////////////////////////////
75 830 : static DBState *ValidateGenId(DBTableBase *table, DBEntry *entry,
76 : DBTableBase::ListenerId id, uint32_t gen_id) {
77 : FlowMgmtDbClient::FlowMgmtState *state =
78 830 : static_cast<FlowMgmtDbClient::FlowMgmtState *>(entry->GetState(table,
79 : id));
80 830 : if (state == NULL)
81 0 : return NULL;
82 :
83 : // If DBEntry is re-added in meanwhile, we do not want to free DBState
84 830 : if (state->deleted_ == false)
85 44 : return NULL;
86 :
87 786 : if (state->gen_id_ > gen_id)
88 3 : return NULL;
89 :
90 783 : return state;
91 : }
92 :
93 81 : void FlowMgmtDbClient::FreeInterfaceState(Interface *intf, uint32_t gen_id) {
94 81 : VmInterface *vm_port = dynamic_cast<VmInterface *>(intf);
95 81 : if (vm_port == NULL)
96 0 : return;
97 :
98 81 : DBState *state = ValidateGenId(intf->get_table(), intf,
99 : interface_listener_id_, gen_id);
100 81 : if (state == NULL)
101 44 : return;
102 :
103 37 : intf->ClearState(intf->get_table(), interface_listener_id_);
104 37 : delete state;
105 : }
106 :
107 234 : void FlowMgmtDbClient::InterfaceNotify(DBTablePartBase *part, DBEntryBase *e) {
108 234 : Interface *intf = static_cast<Interface *>(e);
109 234 : if (intf->type() != Interface::VM_INTERFACE) {
110 25 : return;
111 : }
112 :
113 209 : VmInterface *vm_port = static_cast<VmInterface *>(intf);
114 209 : if (vm_port->device_type() == VmInterface::VMI_ON_LR)
115 0 : return;
116 :
117 209 : const VnEntry *new_vn = vm_port->vn();
118 :
119 : VmIntfFlowHandlerState *state = static_cast<VmIntfFlowHandlerState *>
120 209 : (e->GetState(part->parent(), interface_listener_id_));
121 209 : if (intf->IsDeleted()) {
122 37 : if (state) {
123 37 : DeleteEvent(vm_port, state);
124 : }
125 37 : return;
126 : }
127 :
128 172 : const VmInterface::SecurityGroupEntryList &new_sg_l = vm_port->sg_list();
129 172 : bool changed = false;
130 :
131 172 : if (state == NULL) {
132 37 : state = new VmIntfFlowHandlerState(NULL);
133 37 : e->SetState(part->parent(), interface_listener_id_, state);
134 : // Force change for first time
135 37 : state->policy_ = vm_port->policy_enabled();
136 37 : state->sg_l_ = new_sg_l;
137 37 : state->vn_ = new_vn;
138 37 : state->vrf_assign_acl_ = vm_port->vrf_assign_acl();
139 37 : state->is_vn_qos_config_ = vm_port->is_vn_qos_config();
140 37 : state->qos_config_ = vm_port->qos_config();
141 37 : state->fw_policy_list_ = vm_port->fw_policy_list();
142 37 : state->fwaas_fw_policy_list_ = vm_port->fwaas_fw_policy_list();
143 37 : if (vm_port->forwarding_vrf()) {
144 3 : state->forwarding_vrf_id_ = vm_port->forwarding_vrf()->vrf_id();
145 : }
146 37 : changed = true;
147 : } else {
148 135 : if (state->deleted_) {
149 0 : state->deleted_ = false;
150 0 : changed = true;
151 : }
152 :
153 135 : if (state->vn_.get() != new_vn) {
154 44 : changed = true;
155 44 : state->vn_ = new_vn;
156 : }
157 135 : if (state->policy_ != vm_port->policy_enabled()) {
158 44 : changed = true;
159 44 : state->policy_ = vm_port->policy_enabled();
160 : }
161 135 : if (state->sg_l_.list_ != new_sg_l.list_) {
162 5 : changed = true;
163 5 : state->sg_l_ = new_sg_l;
164 : }
165 135 : if (state->vrf_assign_acl_.get() != vm_port->vrf_assign_acl()) {
166 0 : changed = true;
167 0 : state->vrf_assign_acl_ = vm_port->vrf_assign_acl();
168 : }
169 135 : if (state->is_vn_qos_config_ != vm_port->is_vn_qos_config()) {
170 0 : state->is_vn_qos_config_ = vm_port->is_vn_qos_config();
171 0 : changed = true;
172 : }
173 135 : if (state->qos_config_.get() != vm_port->qos_config()) {
174 0 : state->qos_config_ = vm_port->qos_config();
175 0 : changed = true;
176 : }
177 :
178 135 : if (state->fw_policy_list_ != vm_port->fw_policy_list()) {
179 0 : state->fw_policy_list_ = vm_port->fw_policy_list();
180 0 : changed = true;
181 : }
182 :
183 135 : if (state->fwaas_fw_policy_list_ != vm_port->fwaas_fw_policy_list()) {
184 0 : state->fwaas_fw_policy_list_ = vm_port->fwaas_fw_policy_list();
185 0 : changed = true;
186 : }
187 :
188 135 : uint32_t forwarding_vrf_id = VrfEntry::kInvalidIndex;
189 135 : if (vm_port->forwarding_vrf()) {
190 96 : forwarding_vrf_id = vm_port->forwarding_vrf()->vrf_id();
191 : }
192 :
193 135 : if (state->forwarding_vrf_id_ != forwarding_vrf_id) {
194 44 : state->forwarding_vrf_id_ = forwarding_vrf_id;
195 44 : DeleteAllFlow(vm_port, state);
196 44 : changed = true;
197 : }
198 : }
199 :
200 172 : if (changed) {
201 91 : AddEvent(vm_port, state);
202 : }
203 : }
204 :
205 : ////////////////////////////////////////////////////////////////////////////
206 : // VN notification handler
207 : ////////////////////////////////////////////////////////////////////////////
208 16 : void FlowMgmtDbClient::FreeVnState(VnEntry *vn, uint32_t gen_id) {
209 16 : DBState *state = ValidateGenId(vn->get_table(), vn, vn_listener_id_,
210 : gen_id);
211 16 : if (state == NULL)
212 0 : return;
213 :
214 16 : vn->ClearState(vn->get_table(), vn_listener_id_);
215 16 : delete state;
216 : }
217 :
218 52 : void FlowMgmtDbClient::VnNotify(DBTablePartBase *part, DBEntryBase *e) {
219 : // Add/Delete Acl:
220 : // Resync all Vn flows with new VN network policies
221 52 : VnEntry *vn = static_cast<VnEntry *>(e);
222 : VnFlowHandlerState *state = static_cast<VnFlowHandlerState *>
223 52 : (e->GetState(part->parent(), vn_listener_id_));
224 52 : AclDBEntryConstRef acl = NULL;
225 52 : AclDBEntryConstRef macl = NULL;
226 52 : AclDBEntryConstRef mcacl = NULL;
227 52 : bool enable_rpf = true;
228 52 : bool flood_unknown_unicast = false;
229 :
230 52 : if (vn->IsDeleted()) {
231 16 : if (state) {
232 16 : DeleteEvent(vn, state);
233 : }
234 16 : return;
235 : }
236 :
237 36 : bool changed = false;
238 36 : if (state != NULL) {
239 20 : acl = state->acl_;
240 20 : macl = state->macl_;
241 20 : mcacl = state->mcacl_;
242 20 : enable_rpf = state->enable_rpf_;
243 20 : flood_unknown_unicast = state->flood_unknown_unicast_;
244 : }
245 :
246 36 : const AclDBEntry *new_acl = vn->GetAcl();
247 36 : const AclDBEntry *new_macl = vn->GetMirrorAcl();
248 36 : const AclDBEntry *new_mcacl = vn->GetMirrorCfgAcl();
249 36 : bool new_enable_rpf = vn->enable_rpf();
250 36 : bool new_flood_unknown_unicast = vn->flood_unknown_unicast();
251 :
252 36 : if (state == NULL) {
253 16 : state = new VnFlowHandlerState(new_acl, new_macl, new_mcacl,
254 : new_enable_rpf,
255 16 : new_flood_unknown_unicast);
256 16 : e->SetState(part->parent(), vn_listener_id_, state);
257 16 : changed = true;
258 : }
259 :
260 72 : if (acl != new_acl || macl != new_macl || mcacl !=new_mcacl ||
261 72 : enable_rpf != new_enable_rpf ||
262 : flood_unknown_unicast != new_flood_unknown_unicast) {
263 0 : state->acl_ = new_acl;
264 0 : state->macl_ = new_macl;
265 0 : state->mcacl_ = new_mcacl;
266 0 : state->enable_rpf_ = new_enable_rpf;
267 0 : state->flood_unknown_unicast_ = new_flood_unknown_unicast;
268 0 : changed = true;
269 : }
270 :
271 36 : if (state->deleted_) {
272 0 : state->deleted_ = false;
273 0 : changed = true;
274 : }
275 :
276 36 : if (changed) {
277 16 : AddEvent(vn, state);
278 : }
279 84 : }
280 :
281 : ////////////////////////////////////////////////////////////////////////////
282 : // ACL notification handler
283 : ////////////////////////////////////////////////////////////////////////////
284 4 : void FlowMgmtDbClient::FreeAclState(AclDBEntry *acl, uint32_t gen_id) {
285 4 : DBState *state = ValidateGenId(acl->get_table(), acl, acl_listener_id_,
286 : gen_id);
287 4 : if (state == NULL)
288 0 : return;
289 :
290 4 : acl->ClearState(acl->get_table(), acl_listener_id_);
291 4 : delete state;
292 : }
293 :
294 10 : void FlowMgmtDbClient::AclNotify(DBTablePartBase *part, DBEntryBase *e) {
295 10 : AclDBEntry *acl = static_cast<AclDBEntry *>(e);
296 : AclFlowHandlerState *state =
297 10 : static_cast<AclFlowHandlerState *>(e->GetState(part->parent(),
298 : acl_listener_id_));
299 10 : if (e->IsDeleted()) {
300 4 : if (state) {
301 4 : DeleteEvent(acl, state);
302 : }
303 4 : return;
304 : }
305 :
306 6 : if (!state) {
307 4 : state = new AclFlowHandlerState();
308 4 : e->SetState(part->parent(), acl_listener_id_, state);
309 : }
310 6 : state->deleted_ = false;
311 6 : AddEvent(acl, state);
312 : }
313 :
314 : ////////////////////////////////////////////////////////////////////////////
315 : // NH notification handler
316 : ////////////////////////////////////////////////////////////////////////////
317 423 : void FlowMgmtDbClient::FreeNhState(NextHop *nh, uint32_t gen_id) {
318 423 : DBState *state = ValidateGenId(nh->get_table(), nh, nh_listener_id_,
319 : gen_id);
320 423 : if (state == NULL)
321 0 : return;
322 :
323 423 : nh->ClearState(nh->get_table(), nh_listener_id_);
324 423 : delete state;
325 : }
326 :
327 883 : void FlowMgmtDbClient::NhNotify(DBTablePartBase *part, DBEntryBase *e) {
328 883 : NextHop *nh = static_cast<NextHop *>(e);
329 : NhFlowHandlerState *state =
330 883 : static_cast<NhFlowHandlerState *>(e->GetState(part->parent(),
331 : nh_listener_id_));
332 883 : bool is_tunnel_nh = false;
333 883 : bool changed = false;
334 883 : uint8_t curr_valid_encap_size = 0;
335 883 : uint8_t new_valid_encap_size = 0;
336 883 : if (nh->GetType() == NextHop::TUNNEL && agent_->is_l3mh()) {
337 : const TunnelNH *tunnel_nh =
338 0 : dynamic_cast<const TunnelNH *>(nh);
339 0 : if (tunnel_nh) {
340 0 : is_tunnel_nh = true;
341 0 : TunnelNH::EncapDataList encap_list = tunnel_nh->GetEncapDataList();
342 0 : for (uint8_t i = 0; i < tunnel_nh->GetEncapDataList().size(); i++) {
343 0 : if (encap_list[i].get()->valid_)
344 0 : new_valid_encap_size++;
345 : }
346 0 : }
347 : }
348 :
349 883 : if (nh->IsDeleted()) {
350 425 : if (state) {
351 423 : DeleteEvent(nh, state);
352 : }
353 425 : return;
354 : }
355 :
356 458 : if (state != NULL && is_tunnel_nh && agent_->is_l3mh() ) {
357 0 : curr_valid_encap_size = state->valid_encap_size_;
358 : }
359 :
360 458 : if (!state) {
361 423 : state = new NhFlowHandlerState(new_valid_encap_size);
362 423 : nh->SetState(part->parent(), nh_listener_id_, state);
363 423 : changed = true;
364 : }
365 :
366 458 : if (is_tunnel_nh && agent_->is_l3mh() && new_valid_encap_size != curr_valid_encap_size ) {
367 0 : state->valid_encap_size_ = new_valid_encap_size;
368 0 : changed = true;
369 : }
370 :
371 458 : if (state->deleted_) {
372 0 : state->deleted_ = false;
373 0 : changed = true;
374 : }
375 :
376 458 : if (changed) {
377 423 : AddEvent(nh, state);
378 : }
379 : }
380 :
381 : ////////////////////////////////////////////////////////////////////////////
382 : // VRF Notification handlers
383 : ////////////////////////////////////////////////////////////////////////////
384 35 : void FlowMgmtDbClient::FreeVrfState(VrfEntry *vrf, uint32_t gen_id) {
385 35 : if (vrf->IsDeleted() == false)
386 0 : return;
387 :
388 : VrfFlowHandlerState *state = static_cast<VrfFlowHandlerState *>
389 35 : (ValidateGenId(vrf->get_table(), vrf, vrf_listener_id_, gen_id));
390 35 : if (state == NULL)
391 3 : return;
392 32 : if (state->Unregister(vrf)) {
393 32 : vrf->ClearState(vrf->get_table(), vrf_listener_id_);
394 32 : delete state;
395 : }
396 : }
397 :
398 32 : bool FlowMgmtDbClient::VrfFlowHandlerState::Unregister(VrfEntry *vrf) {
399 : // Register to the Inet4 Unicast Table
400 : InetUnicastAgentRouteTable *inet_table =
401 : static_cast<InetUnicastAgentRouteTable *>
402 32 : (vrf->GetInet4UnicastRouteTable());
403 32 : if (inet_table) {
404 32 : if (inet_table->Size() != 0)
405 0 : return false;
406 32 : if (inet_listener_id_ != DBTableBase::kInvalidId) {
407 32 : inet_table->Unregister(inet_listener_id_);
408 32 : FLOW_TRACE(RouteTableListener,
409 : "ROUTE-TABLE-UNREGISTER",
410 : vrf->GetName(),
411 : inet_table->GetTableName(),
412 : inet_listener_id_);
413 32 : inet_listener_id_ = DBTableBase::kInvalidId;
414 : }
415 : }
416 :
417 : inet_table = static_cast<InetUnicastAgentRouteTable *>
418 32 : (vrf->GetInet6UnicastRouteTable());
419 32 : if (inet_table) {
420 32 : if (inet_table->Size() != 0)
421 0 : return false;
422 32 : if (inet6_listener_id_ != DBTableBase::kInvalidId) {
423 32 : inet_table->Unregister(inet6_listener_id_);
424 32 : FLOW_TRACE(RouteTableListener,
425 : "ROUTE-TABLE-UNREGISTER",
426 : vrf->GetName(),
427 : inet_table->GetTableName(),
428 : inet6_listener_id_);
429 32 : inet6_listener_id_ = DBTableBase::kInvalidId;
430 : }
431 : }
432 :
433 : // Register to the Bridge Unicast Table
434 : BridgeAgentRouteTable *bridge_table =
435 : static_cast<BridgeAgentRouteTable *>
436 32 : (vrf->GetBridgeRouteTable());
437 32 : if (bridge_table) {
438 32 : if (bridge_table->Size() != 0)
439 0 : return false;
440 32 : if (bridge_listener_id_ != DBTableBase::kInvalidId) {
441 32 : bridge_table->Unregister(bridge_listener_id_);
442 32 : FLOW_TRACE(RouteTableListener,
443 : "ROUTE-TABLE-UNREGISTER",
444 : vrf->GetName(),
445 : bridge_table->GetTableName(),
446 : bridge_listener_id_);
447 32 : bridge_listener_id_ = DBTableBase::kInvalidId;
448 : }
449 : }
450 :
451 32 : return true;
452 : }
453 :
454 32 : void FlowMgmtDbClient::VrfFlowHandlerState::Register(FlowMgmtDbClient *client,
455 : VrfEntry *vrf) {
456 : // Register to the Inet4 Unicast Table
457 : InetUnicastAgentRouteTable *inet_table =
458 : static_cast<InetUnicastAgentRouteTable *>
459 32 : (vrf->GetInet4UnicastRouteTable());
460 :
461 32 : inet_listener_id_ =
462 32 : inet_table->Register(boost::bind(&FlowMgmtDbClient::RouteNotify, client,
463 : this, Agent::INET4_UNICAST, _1, _2));
464 32 : FLOW_TRACE(RouteTableListener,
465 : "ROUTE-TABLE-REGISTER",
466 : vrf->GetName(),
467 : inet_table->GetTableName(),
468 : inet_listener_id_);
469 :
470 : inet_table = static_cast<InetUnicastAgentRouteTable *>
471 32 : (vrf->GetInet6UnicastRouteTable());
472 32 : inet6_listener_id_ =
473 32 : inet_table->Register(boost::bind(&FlowMgmtDbClient::RouteNotify, client,
474 : this, Agent::INET6_UNICAST, _1, _2));
475 32 : FLOW_TRACE(RouteTableListener,
476 : "ROUTE-TABLE-REGISTER",
477 : vrf->GetName(),
478 : inet_table->GetTableName(),
479 : inet6_listener_id_);
480 :
481 : // Register to the Bridge Unicast Table
482 : BridgeAgentRouteTable *bridge_table =
483 : static_cast<BridgeAgentRouteTable *>
484 32 : (vrf->GetBridgeRouteTable());
485 32 : bridge_listener_id_ =
486 32 : bridge_table->Register(boost::bind(&FlowMgmtDbClient::RouteNotify,
487 : client, this, Agent::BRIDGE, _1,
488 : _2));
489 32 : FLOW_TRACE(RouteTableListener,
490 : "ROUTE-TABLE-REGISTER",
491 : vrf->GetName(),
492 : bridge_table->GetTableName(),
493 : bridge_listener_id_);
494 32 : }
495 :
496 304 : void FlowMgmtDbClient::VrfNotify(DBTablePartBase *part, DBEntryBase *e) {
497 304 : VrfEntry *vrf = static_cast<VrfEntry *>(e);
498 : VrfFlowHandlerState *state = static_cast<VrfFlowHandlerState *>
499 304 : (e->GetState(part->parent(), vrf_listener_id_));
500 304 : if (vrf->IsDeleted()) {
501 252 : if (state ) {
502 61 : state->deleted_ = true;
503 61 : DeleteEvent(vrf, state);
504 : }
505 252 : return;
506 : }
507 52 : if (state == NULL) {
508 32 : state = new VrfFlowHandlerState();
509 32 : state->Register(this, vrf);
510 32 : vrf->SetState(part->parent(), vrf_listener_id_, state);
511 32 : AddEvent(vrf, state);
512 : }
513 52 : state->deleted_ = false;
514 52 : return;
515 : }
516 :
517 : /////////////////////////////////////////////////////////////////////////////
518 : // FlowTableRequest handlers for Routes
519 : /////////////////////////////////////////////////////////////////////////////
520 1043 : void FlowMgmtDbClient::TraceMsg(AgentRoute *entry, const AgentPath *path,
521 : const SecurityGroupList &sg_list, bool deleted) {
522 1043 : std::vector<std::string> vn_list;
523 1043 : if (path) {
524 744 : path->GetDestinationVnList(&vn_list);
525 : }
526 1043 : InetUnicastRouteEntry *inet = dynamic_cast<InetUnicastRouteEntry *>(entry);
527 1043 : if (inet) {
528 367 : FLOW_TRACE(RouteUpdate,
529 : inet->vrf()->GetName(),
530 : inet->prefix_address().to_string(),
531 : inet->prefix_length(),
532 : vn_list,
533 : inet->IsDeleted(),
534 : deleted,
535 : sg_list.size(),
536 : sg_list);
537 : }
538 :
539 1043 : BridgeRouteEntry *bridge = dynamic_cast<BridgeRouteEntry *>(entry);
540 1043 : if (bridge) {
541 676 : FLOW_TRACE(RouteUpdate,
542 : bridge->vrf()->GetName(),
543 : bridge->prefix_address().ToString(),
544 : bridge->prefix_length(),
545 : vn_list,
546 : bridge->IsDeleted(),
547 : deleted,
548 : sg_list.size(),
549 : sg_list);
550 : }
551 1043 : }
552 :
553 271 : void FlowMgmtDbClient::FreeRouteState(AgentRoute *route, uint32_t gen_id) {
554 271 : if (route->IsDeleted() == false)
555 0 : return;
556 :
557 271 : VrfEntry *vrf = route->vrf();
558 : VrfFlowHandlerState *vrf_state = static_cast<VrfFlowHandlerState *>
559 271 : (vrf->GetState(vrf->get_table(), vrf_listener_id_));
560 271 : if (vrf_state == NULL)
561 0 : return;
562 :
563 : DBTableBase::ListenerId id;
564 271 : if (dynamic_cast<InetUnicastRouteEntry *>(route)) {
565 119 : if (route->GetTableType() == Agent::INET4_UNICAST)
566 75 : id = vrf_state->inet_listener_id_;
567 : else
568 44 : id = vrf_state->inet6_listener_id_;
569 152 : } else if (dynamic_cast<BridgeRouteEntry *>(route)) {
570 152 : id = vrf_state->bridge_listener_id_;
571 : } else {
572 0 : return;
573 : }
574 :
575 271 : DBState *state = ValidateGenId(route->get_table(), route, id, gen_id);
576 271 : if (state == NULL)
577 0 : return;
578 :
579 271 : route->ClearState(route->get_table(), id);
580 271 : delete state;
581 : }
582 :
583 564 : bool FlowMgmtDbClient::HandleTrackingIpChange(const AgentRoute *rt,
584 : RouteFlowHandlerState *state) {
585 564 : bool ret = false;
586 564 : RouteFlowHandlerState::FixedIpMap new_map;
587 :
588 : //Maintain a list of interface to fixed-ip mapping for
589 : //a given route, we need this map because there can be
590 : //multiple path from different local vm path peer.
591 : //If the route has fixed-ip change then all the the flows
592 : //dependent on this route will be reevaluated.
593 1382 : for(Route::PathList::const_iterator it = rt->GetPathList().begin();
594 2764 : it != rt->GetPathList().end(); it++) {
595 818 : const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
596 818 : const Peer *peer = path->peer();
597 818 : if (peer && peer->GetType() != Peer::LOCAL_VM_PORT_PEER) {
598 818 : continue;
599 : }
600 :
601 164 : if (path->nexthop() == NULL ||
602 82 : path->nexthop()->GetType() != NextHop::INTERFACE) {
603 7 : continue;
604 : }
605 :
606 75 : const InterfaceNH *nh = static_cast<InterfaceNH *>(path->nexthop());
607 75 : InterfaceConstRef intf = nh->GetInterface();
608 :
609 75 : IpAddress new_fixed_ip = path->GetFixedIp();
610 75 : if (new_fixed_ip == Ip4Address(0)) {
611 75 : continue;
612 : }
613 :
614 0 : new_map.insert(RouteFlowHandlerState::FixedIpEntry(intf, new_fixed_ip));
615 :
616 : RouteFlowHandlerState::FixedIpMap::const_iterator old_it =
617 0 : state->fixed_ip_map_.find(intf);
618 0 : if (old_it != state->fixed_ip_map_.end()) {
619 0 : if (new_fixed_ip != old_it->second) {
620 0 : ret = true;
621 : }
622 : }
623 75 : }
624 :
625 : //Check if any path has been deleted
626 : RouteFlowHandlerState::FixedIpMap::const_iterator old_it =
627 564 : state->fixed_ip_map_.begin();
628 564 : for (;old_it != state->fixed_ip_map_.end(); old_it++) {
629 0 : if (new_map.find(old_it->first) == new_map.end()) {
630 0 : ret = true;
631 0 : break;
632 : }
633 : }
634 :
635 564 : state->fixed_ip_map_ = new_map;
636 564 : return ret;
637 564 : }
638 :
639 1043 : void FlowMgmtDbClient::RouteNotify(VrfFlowHandlerState *vrf_state,
640 : Agent::RouteTableType type,
641 : DBTablePartBase *partition, DBEntryBase *e) {
642 1043 : DBTableBase::ListenerId id = vrf_state->GetListenerId(type);
643 : RouteFlowHandlerState *state =
644 1043 : static_cast<RouteFlowHandlerState *>(e->GetState(partition->parent(),
645 : id));
646 1043 : AgentRoute *route = static_cast<AgentRoute *>(e);
647 1043 : const AgentPath *path = route->GetActivePath();
648 1043 : SecurityGroupList new_sg_l;
649 : // Get new sg-list. Sort, the sg-list to aid in comparison
650 1043 : if (path) {
651 744 : new_sg_l = route->GetActivePath()->sg_list();
652 744 : sort(new_sg_l.begin(), new_sg_l.end());
653 : }
654 1043 : TraceMsg(route, path, new_sg_l, vrf_state->deleted_);
655 :
656 1043 : if (route->IsDeleted()) {
657 299 : if (state) {
658 271 : DeleteEvent(route, state);
659 : }
660 299 : return;
661 : }
662 :
663 744 : if (vrf_state->deleted_) {
664 : // ignore route add/change for delete notified VRF.
665 1 : return;
666 : }
667 :
668 743 : if (route->is_multicast()) {
669 179 : return;
670 : }
671 :
672 564 : bool new_route = false;
673 564 : if (state == NULL) {
674 271 : state = new RouteFlowHandlerState();
675 271 : route->SetState(partition->parent(), id, state);
676 271 : AddEvent(route, state);
677 271 : new_route = true;
678 : } else {
679 293 : if (state->deleted_) {
680 0 : state->deleted_ = false;
681 0 : new_route = true;
682 : }
683 : }
684 :
685 564 : bool changed = false;
686 564 : bool inet_rt_nh_changed = false;
687 : // Handle SG change
688 564 : if (state->sg_l_ != new_sg_l) {
689 21 : state->sg_l_ = new_sg_l;
690 21 : changed = true;
691 : }
692 :
693 : InetUnicastRouteEntry *inet_route =
694 564 : dynamic_cast<InetUnicastRouteEntry *>(route);
695 : //Trigger RPF NH sync, if active nexthop changes
696 564 : const NextHop *active_nh = route->GetActiveNextHop();
697 564 : const NextHop *local_nh = NULL;
698 564 : if (active_nh && (active_nh->GetType() == NextHop::COMPOSITE)) {
699 : //If destination is ecmp, all remote flow would
700 : //have RPF NH set to that local component NH
701 9 : local_nh = EcmpData::GetLocalNextHop(route);
702 : }
703 :
704 564 : if ((state->active_nh_ != active_nh) || (state->local_nh_ != local_nh)) {
705 283 : state->active_nh_ = active_nh;
706 283 : state->local_nh_ = local_nh;
707 : /* NH change can result in change of DMAC for the following routes, if
708 : * they point to L2 flows.So we need to delete these L2 flows to trigger
709 : * packet to be trapped again for flows which will have the new DMAC.
710 : * The InetRoutes whose NH change has to be tracked are
711 : * Ipv4 InetRoutes which have prefix < 32
712 : * Ipv6 InetRoutes which have prefix < 128
713 : */
714 283 : if (inet_route) {
715 124 : uint8_t plen = inet_route->prefix_length();
716 276 : if ((inet_route->prefix_address().is_v4() && plen < 32) ||
717 152 : (inet_route->prefix_address().is_v6() && plen < 128)) {
718 19 : inet_rt_nh_changed = true;
719 : } else {
720 105 : new_route = true;
721 : }
722 : } else {
723 159 : new_route = true;
724 : }
725 : }
726 :
727 564 : if (HandleTrackingIpChange(route, state)) {
728 : //Tracking IP change can result in flow change
729 : //i.e in case of NAT new reverse flow might be
730 : //created, hence enqueue a ADD event so that flow will
731 : //be reevaluated.
732 0 : new_route = true;
733 : }
734 :
735 564 : if (state->ecmp_load_balance_ != path->ecmp_load_balance()) {
736 0 : state->ecmp_load_balance_ = path->ecmp_load_balance();
737 0 : changed = true;
738 : }
739 :
740 564 : if (state->tags_l_ != path->tag_list()) {
741 0 : state->tags_l_ = path->tag_list();
742 0 : changed = true;
743 : }
744 :
745 564 : if (state->tunnel_bmap_ != path->tunnel_bmap()) {
746 250 : state->tunnel_bmap_ = path->tunnel_bmap();
747 250 : changed = true;
748 : }
749 :
750 564 : if (new_route == true) {
751 283 : AddEvent(route, state);
752 281 : } else if (inet_rt_nh_changed == true) {
753 0 : RouteNHChangeEvent(route, state);
754 281 : } else if (changed == true) {
755 11 : ChangeEvent(route, state);
756 : }
757 1043 : }
758 :
759 : /////////////////////////////////////////////////////////////////////////////
760 : // FlowTableRequest message handler
761 : /////////////////////////////////////////////////////////////////////////////
762 830 : bool FlowMgmtDbClient::FreeDBState(const DBEntry *entry, uint32_t gen_id) {
763 830 : if (dynamic_cast<const Interface *>(entry)) {
764 81 : DBTable *table = agent_->interface_table();
765 81 : Interface *intf = static_cast<Interface *>(table->Find(entry));
766 81 : FreeInterfaceState(intf, gen_id);
767 81 : return true;
768 : }
769 :
770 749 : if (dynamic_cast<const VnEntry *>(entry)) {
771 16 : DBTable *table = agent_->vn_table();
772 16 : VnEntry *vn = static_cast<VnEntry *>(table->Find(entry));
773 16 : FreeVnState(vn, gen_id);
774 16 : return true;
775 : }
776 :
777 733 : if (dynamic_cast<const AclDBEntry *>(entry)) {
778 4 : DBTable *table = agent_->acl_table();
779 4 : AclDBEntry *acl = static_cast<AclDBEntry *> (table->Find(entry));
780 4 : FreeAclState(acl, gen_id);
781 4 : return true;
782 : }
783 :
784 729 : if (dynamic_cast<const NextHop *>(entry)) {
785 423 : DBTable *table = agent_->nexthop_table();
786 423 : NextHop *nh = static_cast<NextHop *> (table->Find(entry));
787 423 : FreeNhState(nh, gen_id);
788 423 : return true;
789 : }
790 :
791 306 : if (dynamic_cast<const VrfEntry *>(entry)) {
792 35 : DBTable *table = agent_->vrf_table();
793 35 : VrfEntry *vrf = static_cast<VrfEntry *> (table->Find(entry));
794 35 : FreeVrfState(vrf, gen_id);
795 35 : return true;
796 : }
797 :
798 271 : if (dynamic_cast<const AgentRoute *>(entry)) {
799 271 : VrfEntry *vrf = (static_cast<const AgentRoute *>(entry))->vrf();
800 271 : AgentRoute *rt = NULL;
801 271 : if (dynamic_cast<const InetUnicastRouteEntry *>(entry)) {
802 119 : DBTable *table = NULL;
803 119 : if ((dynamic_cast<const AgentRoute *>(entry))->GetTableType()
804 119 : == Agent::INET4_UNICAST)
805 75 : table = vrf->GetInet4UnicastRouteTable();
806 : else
807 44 : table = vrf->GetInet6UnicastRouteTable();
808 119 : rt = static_cast<AgentRoute *>(table->Find(entry));
809 : } else {
810 152 : DBTable *table = vrf->GetBridgeRouteTable();
811 152 : rt = static_cast<AgentRoute *>(table->Find(entry));
812 : }
813 271 : FreeRouteState(rt, gen_id);
814 271 : return true;
815 : }
816 :
817 0 : assert(0);
818 : return true;
819 : }
|