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 500 : void FlowMgmtDbClient::AddEvent(const DBEntry *entry, FlowMgmtState *state) {
49 500 : mgr_->AddDBEntryEvent(entry, state->gen_id_);
50 500 : }
51 :
52 336 : void FlowMgmtDbClient::DeleteEvent(const DBEntry *entry, FlowMgmtState *state) {
53 336 : state->gen_id_++;
54 336 : state->deleted_ = true;
55 336 : mgr_->DeleteDBEntryEvent(entry, state->gen_id_);
56 336 : }
57 :
58 14 : void FlowMgmtDbClient::DeleteAllFlow(const DBEntry *entry,
59 : FlowMgmtState *state) {
60 14 : mgr_->DeleteDBEntryEvent(entry, state->gen_id_);
61 14 : }
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 344 : static DBState *ValidateGenId(DBTableBase *table, DBEntry *entry,
76 : DBTableBase::ListenerId id, uint32_t gen_id) {
77 : FlowMgmtDbClient::FlowMgmtState *state =
78 344 : static_cast<FlowMgmtDbClient::FlowMgmtState *>(entry->GetState(table,
79 : id));
80 344 : if (state == NULL)
81 0 : return NULL;
82 :
83 : // If DBEntry is re-added in meanwhile, we do not want to free DBState
84 344 : if (state->deleted_ == false)
85 14 : return NULL;
86 :
87 330 : if (state->gen_id_ > gen_id)
88 0 : return NULL;
89 :
90 330 : return state;
91 : }
92 :
93 31 : void FlowMgmtDbClient::FreeInterfaceState(Interface *intf, uint32_t gen_id) {
94 31 : VmInterface *vm_port = dynamic_cast<VmInterface *>(intf);
95 31 : if (vm_port == NULL)
96 0 : return;
97 :
98 31 : DBState *state = ValidateGenId(intf->get_table(), intf,
99 : interface_listener_id_, gen_id);
100 31 : if (state == NULL)
101 14 : return;
102 :
103 17 : intf->ClearState(intf->get_table(), interface_listener_id_);
104 17 : delete state;
105 : }
106 :
107 98 : void FlowMgmtDbClient::InterfaceNotify(DBTablePartBase *part, DBEntryBase *e) {
108 98 : Interface *intf = static_cast<Interface *>(e);
109 98 : if (intf->type() != Interface::VM_INTERFACE) {
110 27 : return;
111 : }
112 :
113 71 : VmInterface *vm_port = static_cast<VmInterface *>(intf);
114 71 : if (vm_port->device_type() == VmInterface::VMI_ON_LR)
115 0 : return;
116 :
117 71 : const VnEntry *new_vn = vm_port->vn();
118 :
119 : VmIntfFlowHandlerState *state = static_cast<VmIntfFlowHandlerState *>
120 71 : (e->GetState(part->parent(), interface_listener_id_));
121 71 : if (intf->IsDeleted()) {
122 17 : if (state) {
123 17 : DeleteEvent(vm_port, state);
124 : }
125 17 : return;
126 : }
127 :
128 54 : const VmInterface::SecurityGroupEntryList &new_sg_l = vm_port->sg_list();
129 54 : bool changed = false;
130 :
131 54 : if (state == NULL) {
132 17 : state = new VmIntfFlowHandlerState(NULL);
133 17 : e->SetState(part->parent(), interface_listener_id_, state);
134 : // Force change for first time
135 17 : state->policy_ = vm_port->policy_enabled();
136 17 : state->sg_l_ = new_sg_l;
137 17 : state->vn_ = new_vn;
138 17 : state->vrf_assign_acl_ = vm_port->vrf_assign_acl();
139 17 : state->is_vn_qos_config_ = vm_port->is_vn_qos_config();
140 17 : state->qos_config_ = vm_port->qos_config();
141 17 : state->fw_policy_list_ = vm_port->fw_policy_list();
142 17 : state->fwaas_fw_policy_list_ = vm_port->fwaas_fw_policy_list();
143 17 : if (vm_port->forwarding_vrf()) {
144 3 : state->forwarding_vrf_id_ = vm_port->forwarding_vrf()->vrf_id();
145 : }
146 17 : changed = true;
147 : } else {
148 37 : if (state->deleted_) {
149 0 : state->deleted_ = false;
150 0 : changed = true;
151 : }
152 :
153 37 : if (state->vn_.get() != new_vn) {
154 14 : changed = true;
155 14 : state->vn_ = new_vn;
156 : }
157 37 : if (state->policy_ != vm_port->policy_enabled()) {
158 14 : changed = true;
159 14 : state->policy_ = vm_port->policy_enabled();
160 : }
161 37 : if (state->sg_l_.list_ != new_sg_l.list_) {
162 5 : changed = true;
163 5 : state->sg_l_ = new_sg_l;
164 : }
165 37 : 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 37 : 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 37 : 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 37 : 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 37 : 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 37 : uint32_t forwarding_vrf_id = VrfEntry::kInvalidIndex;
189 37 : if (vm_port->forwarding_vrf()) {
190 28 : forwarding_vrf_id = vm_port->forwarding_vrf()->vrf_id();
191 : }
192 :
193 37 : if (state->forwarding_vrf_id_ != forwarding_vrf_id) {
194 14 : state->forwarding_vrf_id_ = forwarding_vrf_id;
195 14 : DeleteAllFlow(vm_port, state);
196 14 : changed = true;
197 : }
198 : }
199 :
200 54 : if (changed) {
201 41 : AddEvent(vm_port, state);
202 : }
203 : }
204 :
205 : ////////////////////////////////////////////////////////////////////////////
206 : // VN notification handler
207 : ////////////////////////////////////////////////////////////////////////////
208 6 : void FlowMgmtDbClient::FreeVnState(VnEntry *vn, uint32_t gen_id) {
209 6 : DBState *state = ValidateGenId(vn->get_table(), vn, vn_listener_id_,
210 : gen_id);
211 6 : if (state == NULL)
212 0 : return;
213 :
214 6 : vn->ClearState(vn->get_table(), vn_listener_id_);
215 6 : delete state;
216 : }
217 :
218 19 : void FlowMgmtDbClient::VnNotify(DBTablePartBase *part, DBEntryBase *e) {
219 : // Add/Delete Acl:
220 : // Resync all Vn flows with new VN network policies
221 19 : VnEntry *vn = static_cast<VnEntry *>(e);
222 : VnFlowHandlerState *state = static_cast<VnFlowHandlerState *>
223 19 : (e->GetState(part->parent(), vn_listener_id_));
224 19 : AclDBEntryConstRef acl = NULL;
225 19 : AclDBEntryConstRef macl = NULL;
226 19 : AclDBEntryConstRef mcacl = NULL;
227 19 : bool enable_rpf = true;
228 19 : bool flood_unknown_unicast = false;
229 :
230 19 : if (vn->IsDeleted()) {
231 6 : if (state) {
232 6 : DeleteEvent(vn, state);
233 : }
234 6 : return;
235 : }
236 :
237 13 : bool changed = false;
238 13 : if (state != NULL) {
239 7 : acl = state->acl_;
240 7 : macl = state->macl_;
241 7 : mcacl = state->mcacl_;
242 7 : enable_rpf = state->enable_rpf_;
243 7 : flood_unknown_unicast = state->flood_unknown_unicast_;
244 : }
245 :
246 13 : const AclDBEntry *new_acl = vn->GetAcl();
247 13 : const AclDBEntry *new_macl = vn->GetMirrorAcl();
248 13 : const AclDBEntry *new_mcacl = vn->GetMirrorCfgAcl();
249 13 : bool new_enable_rpf = vn->enable_rpf();
250 13 : bool new_flood_unknown_unicast = vn->flood_unknown_unicast();
251 :
252 13 : if (state == NULL) {
253 6 : state = new VnFlowHandlerState(new_acl, new_macl, new_mcacl,
254 : new_enable_rpf,
255 6 : new_flood_unknown_unicast);
256 6 : e->SetState(part->parent(), vn_listener_id_, state);
257 6 : changed = true;
258 : }
259 :
260 26 : if (acl != new_acl || macl != new_macl || mcacl !=new_mcacl ||
261 26 : 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 13 : if (state->deleted_) {
272 0 : state->deleted_ = false;
273 0 : changed = true;
274 : }
275 :
276 13 : if (changed) {
277 6 : AddEvent(vn, state);
278 : }
279 31 : }
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 160 : void FlowMgmtDbClient::FreeNhState(NextHop *nh, uint32_t gen_id) {
318 160 : DBState *state = ValidateGenId(nh->get_table(), nh, nh_listener_id_,
319 : gen_id);
320 160 : if (state == NULL)
321 0 : return;
322 :
323 160 : nh->ClearState(nh->get_table(), nh_listener_id_);
324 160 : delete state;
325 : }
326 :
327 321 : void FlowMgmtDbClient::NhNotify(DBTablePartBase *part, DBEntryBase *e) {
328 321 : NextHop *nh = static_cast<NextHop *>(e);
329 : NhFlowHandlerState *state =
330 321 : static_cast<NhFlowHandlerState *>(e->GetState(part->parent(),
331 : nh_listener_id_));
332 321 : bool is_tunnel_nh = false;
333 321 : bool changed = false;
334 321 : uint8_t curr_valid_encap_size = 0;
335 321 : uint8_t new_valid_encap_size = 0;
336 321 : 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 321 : if (nh->IsDeleted()) {
350 160 : if (state) {
351 160 : DeleteEvent(nh, state);
352 : }
353 160 : return;
354 : }
355 :
356 161 : if (state != NULL && is_tunnel_nh && agent_->is_l3mh() ) {
357 0 : curr_valid_encap_size = state->valid_encap_size_;
358 : }
359 :
360 161 : if (!state) {
361 160 : state = new NhFlowHandlerState(new_valid_encap_size);
362 160 : nh->SetState(part->parent(), nh_listener_id_, state);
363 160 : changed = true;
364 : }
365 :
366 161 : 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 161 : if (state->deleted_) {
372 0 : state->deleted_ = false;
373 0 : changed = true;
374 : }
375 :
376 161 : if (changed) {
377 160 : AddEvent(nh, state);
378 : }
379 : }
380 :
381 : ////////////////////////////////////////////////////////////////////////////
382 : // VRF Notification handlers
383 : ////////////////////////////////////////////////////////////////////////////
384 12 : void FlowMgmtDbClient::FreeVrfState(VrfEntry *vrf, uint32_t gen_id) {
385 12 : if (vrf->IsDeleted() == false)
386 0 : return;
387 :
388 : VrfFlowHandlerState *state = static_cast<VrfFlowHandlerState *>
389 12 : (ValidateGenId(vrf->get_table(), vrf, vrf_listener_id_, gen_id));
390 12 : if (state == NULL)
391 0 : return;
392 12 : if (state->Unregister(vrf)) {
393 12 : vrf->ClearState(vrf->get_table(), vrf_listener_id_);
394 12 : delete state;
395 : }
396 : }
397 :
398 12 : bool FlowMgmtDbClient::VrfFlowHandlerState::Unregister(VrfEntry *vrf) {
399 : // Register to the Inet4 Unicast Table
400 : InetUnicastAgentRouteTable *inet_table =
401 : static_cast<InetUnicastAgentRouteTable *>
402 12 : (vrf->GetInet4UnicastRouteTable());
403 12 : if (inet_table) {
404 12 : if (inet_table->Size() != 0)
405 0 : return false;
406 12 : if (inet_listener_id_ != DBTableBase::kInvalidId) {
407 12 : inet_table->Unregister(inet_listener_id_);
408 12 : FLOW_TRACE(RouteTableListener,
409 : "ROUTE-TABLE-UNREGISTER",
410 : vrf->GetName(),
411 : inet_table->GetTableName(),
412 : inet_listener_id_);
413 12 : inet_listener_id_ = DBTableBase::kInvalidId;
414 : }
415 : }
416 :
417 : inet_table = static_cast<InetUnicastAgentRouteTable *>
418 12 : (vrf->GetInet6UnicastRouteTable());
419 12 : if (inet_table) {
420 12 : if (inet_table->Size() != 0)
421 0 : return false;
422 12 : if (inet6_listener_id_ != DBTableBase::kInvalidId) {
423 12 : inet_table->Unregister(inet6_listener_id_);
424 12 : FLOW_TRACE(RouteTableListener,
425 : "ROUTE-TABLE-UNREGISTER",
426 : vrf->GetName(),
427 : inet_table->GetTableName(),
428 : inet6_listener_id_);
429 12 : inet6_listener_id_ = DBTableBase::kInvalidId;
430 : }
431 : }
432 :
433 : // Register to the Bridge Unicast Table
434 : BridgeAgentRouteTable *bridge_table =
435 : static_cast<BridgeAgentRouteTable *>
436 12 : (vrf->GetBridgeRouteTable());
437 12 : if (bridge_table) {
438 12 : if (bridge_table->Size() != 0)
439 0 : return false;
440 12 : if (bridge_listener_id_ != DBTableBase::kInvalidId) {
441 12 : bridge_table->Unregister(bridge_listener_id_);
442 12 : FLOW_TRACE(RouteTableListener,
443 : "ROUTE-TABLE-UNREGISTER",
444 : vrf->GetName(),
445 : bridge_table->GetTableName(),
446 : bridge_listener_id_);
447 12 : bridge_listener_id_ = DBTableBase::kInvalidId;
448 : }
449 : }
450 :
451 12 : return true;
452 : }
453 :
454 12 : 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 12 : (vrf->GetInet4UnicastRouteTable());
460 :
461 12 : inet_listener_id_ =
462 12 : inet_table->Register(boost::bind(&FlowMgmtDbClient::RouteNotify, client,
463 : this, Agent::INET4_UNICAST, _1, _2));
464 12 : 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 12 : (vrf->GetInet6UnicastRouteTable());
472 12 : inet6_listener_id_ =
473 12 : inet_table->Register(boost::bind(&FlowMgmtDbClient::RouteNotify, client,
474 : this, Agent::INET6_UNICAST, _1, _2));
475 12 : 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 12 : (vrf->GetBridgeRouteTable());
485 12 : bridge_listener_id_ =
486 12 : bridge_table->Register(boost::bind(&FlowMgmtDbClient::RouteNotify,
487 : client, this, Agent::BRIDGE, _1,
488 : _2));
489 12 : FLOW_TRACE(RouteTableListener,
490 : "ROUTE-TABLE-REGISTER",
491 : vrf->GetName(),
492 : bridge_table->GetTableName(),
493 : bridge_listener_id_);
494 12 : }
495 :
496 106 : void FlowMgmtDbClient::VrfNotify(DBTablePartBase *part, DBEntryBase *e) {
497 106 : VrfEntry *vrf = static_cast<VrfEntry *>(e);
498 : VrfFlowHandlerState *state = static_cast<VrfFlowHandlerState *>
499 106 : (e->GetState(part->parent(), vrf_listener_id_));
500 106 : if (vrf->IsDeleted()) {
501 88 : if (state ) {
502 18 : state->deleted_ = true;
503 18 : DeleteEvent(vrf, state);
504 : }
505 88 : return;
506 : }
507 18 : if (state == NULL) {
508 12 : state = new VrfFlowHandlerState();
509 12 : state->Register(this, vrf);
510 12 : vrf->SetState(part->parent(), vrf_listener_id_, state);
511 12 : AddEvent(vrf, state);
512 : }
513 18 : state->deleted_ = false;
514 18 : return;
515 : }
516 :
517 : /////////////////////////////////////////////////////////////////////////////
518 : // FlowTableRequest handlers for Routes
519 : /////////////////////////////////////////////////////////////////////////////
520 546 : void FlowMgmtDbClient::TraceMsg(AgentRoute *entry, const AgentPath *path,
521 : const SecurityGroupList &sg_list, bool deleted) {
522 546 : std::vector<std::string> vn_list;
523 546 : if (path) {
524 409 : path->GetDestinationVnList(&vn_list);
525 : }
526 546 : InetUnicastRouteEntry *inet = dynamic_cast<InetUnicastRouteEntry *>(entry);
527 546 : if (inet) {
528 309 : 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 546 : BridgeRouteEntry *bridge = dynamic_cast<BridgeRouteEntry *>(entry);
540 546 : if (bridge) {
541 237 : 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 546 : }
552 :
553 131 : void FlowMgmtDbClient::FreeRouteState(AgentRoute *route, uint32_t gen_id) {
554 131 : if (route->IsDeleted() == false)
555 0 : return;
556 :
557 131 : VrfEntry *vrf = route->vrf();
558 : VrfFlowHandlerState *vrf_state = static_cast<VrfFlowHandlerState *>
559 131 : (vrf->GetState(vrf->get_table(), vrf_listener_id_));
560 131 : if (vrf_state == NULL)
561 0 : return;
562 :
563 : DBTableBase::ListenerId id;
564 131 : if (dynamic_cast<InetUnicastRouteEntry *>(route)) {
565 79 : if (route->GetTableType() == Agent::INET4_UNICAST)
566 55 : id = vrf_state->inet_listener_id_;
567 : else
568 24 : id = vrf_state->inet6_listener_id_;
569 52 : } else if (dynamic_cast<BridgeRouteEntry *>(route)) {
570 52 : id = vrf_state->bridge_listener_id_;
571 : } else {
572 0 : return;
573 : }
574 :
575 131 : DBState *state = ValidateGenId(route->get_table(), route, id, gen_id);
576 131 : if (state == NULL)
577 0 : return;
578 :
579 131 : route->ClearState(route->get_table(), id);
580 131 : delete state;
581 : }
582 :
583 368 : bool FlowMgmtDbClient::HandleTrackingIpChange(const AgentRoute *rt,
584 : RouteFlowHandlerState *state) {
585 368 : bool ret = false;
586 368 : 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 932 : for(Route::PathList::const_iterator it = rt->GetPathList().begin();
594 1864 : it != rt->GetPathList().end(); it++) {
595 564 : const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
596 564 : const Peer *peer = path->peer();
597 564 : if (peer && peer->GetType() != Peer::LOCAL_VM_PORT_PEER) {
598 564 : continue;
599 : }
600 :
601 184 : if (path->nexthop() == NULL ||
602 92 : path->nexthop()->GetType() != NextHop::INTERFACE) {
603 9 : continue;
604 : }
605 :
606 83 : const InterfaceNH *nh = static_cast<InterfaceNH *>(path->nexthop());
607 83 : InterfaceConstRef intf = nh->GetInterface();
608 :
609 83 : IpAddress new_fixed_ip = path->GetFixedIp();
610 83 : if (new_fixed_ip == Ip4Address(0)) {
611 83 : 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 83 : }
624 :
625 : //Check if any path has been deleted
626 : RouteFlowHandlerState::FixedIpMap::const_iterator old_it =
627 368 : state->fixed_ip_map_.begin();
628 368 : 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 368 : state->fixed_ip_map_ = new_map;
636 368 : return ret;
637 368 : }
638 :
639 546 : void FlowMgmtDbClient::RouteNotify(VrfFlowHandlerState *vrf_state,
640 : Agent::RouteTableType type,
641 : DBTablePartBase *partition, DBEntryBase *e) {
642 546 : DBTableBase::ListenerId id = vrf_state->GetListenerId(type);
643 : RouteFlowHandlerState *state =
644 546 : static_cast<RouteFlowHandlerState *>(e->GetState(partition->parent(),
645 : id));
646 546 : AgentRoute *route = static_cast<AgentRoute *>(e);
647 546 : const AgentPath *path = route->GetActivePath();
648 546 : SecurityGroupList new_sg_l;
649 : // Get new sg-list. Sort, the sg-list to aid in comparison
650 546 : if (path) {
651 409 : new_sg_l = route->GetActivePath()->sg_list();
652 409 : sort(new_sg_l.begin(), new_sg_l.end());
653 : }
654 546 : TraceMsg(route, path, new_sg_l, vrf_state->deleted_);
655 :
656 546 : if (route->IsDeleted()) {
657 137 : if (state) {
658 131 : DeleteEvent(route, state);
659 : }
660 137 : return;
661 : }
662 :
663 409 : if (vrf_state->deleted_) {
664 : // ignore route add/change for delete notified VRF.
665 0 : return;
666 : }
667 :
668 409 : if (route->is_multicast()) {
669 41 : return;
670 : }
671 :
672 368 : bool new_route = false;
673 368 : if (state == NULL) {
674 131 : state = new RouteFlowHandlerState();
675 131 : route->SetState(partition->parent(), id, state);
676 131 : AddEvent(route, state);
677 131 : new_route = true;
678 : } else {
679 237 : if (state->deleted_) {
680 0 : state->deleted_ = false;
681 0 : new_route = true;
682 : }
683 : }
684 :
685 368 : bool changed = false;
686 368 : bool inet_rt_nh_changed = false;
687 : // Handle SG change
688 368 : 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 368 : dynamic_cast<InetUnicastRouteEntry *>(route);
695 : //Trigger RPF NH sync, if active nexthop changes
696 368 : const NextHop *active_nh = route->GetActiveNextHop();
697 368 : const NextHop *local_nh = NULL;
698 368 : 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 368 : if ((state->active_nh_ != active_nh) || (state->local_nh_ != local_nh)) {
705 144 : state->active_nh_ = active_nh;
706 144 : 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 144 : if (inet_route) {
715 85 : uint8_t plen = inet_route->prefix_length();
716 178 : if ((inet_route->prefix_address().is_v4() && plen < 32) ||
717 93 : (inet_route->prefix_address().is_v6() && plen < 128)) {
718 19 : inet_rt_nh_changed = true;
719 : } else {
720 66 : new_route = true;
721 : }
722 : } else {
723 59 : new_route = true;
724 : }
725 : }
726 :
727 368 : 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 368 : 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 368 : if (state->tags_l_ != path->tag_list()) {
741 0 : state->tags_l_ = path->tag_list();
742 0 : changed = true;
743 : }
744 :
745 368 : if (state->tunnel_bmap_ != path->tunnel_bmap()) {
746 132 : state->tunnel_bmap_ = path->tunnel_bmap();
747 132 : changed = true;
748 : }
749 :
750 368 : if (new_route == true) {
751 144 : AddEvent(route, state);
752 224 : } else if (inet_rt_nh_changed == true) {
753 0 : RouteNHChangeEvent(route, state);
754 224 : } else if (changed == true) {
755 11 : ChangeEvent(route, state);
756 : }
757 546 : }
758 :
759 : /////////////////////////////////////////////////////////////////////////////
760 : // FlowTableRequest message handler
761 : /////////////////////////////////////////////////////////////////////////////
762 344 : bool FlowMgmtDbClient::FreeDBState(const DBEntry *entry, uint32_t gen_id) {
763 344 : if (dynamic_cast<const Interface *>(entry)) {
764 31 : DBTable *table = agent_->interface_table();
765 31 : Interface *intf = static_cast<Interface *>(table->Find(entry));
766 31 : FreeInterfaceState(intf, gen_id);
767 31 : return true;
768 : }
769 :
770 313 : if (dynamic_cast<const VnEntry *>(entry)) {
771 6 : DBTable *table = agent_->vn_table();
772 6 : VnEntry *vn = static_cast<VnEntry *>(table->Find(entry));
773 6 : FreeVnState(vn, gen_id);
774 6 : return true;
775 : }
776 :
777 307 : 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 303 : if (dynamic_cast<const NextHop *>(entry)) {
785 160 : DBTable *table = agent_->nexthop_table();
786 160 : NextHop *nh = static_cast<NextHop *> (table->Find(entry));
787 160 : FreeNhState(nh, gen_id);
788 160 : return true;
789 : }
790 :
791 143 : if (dynamic_cast<const VrfEntry *>(entry)) {
792 12 : DBTable *table = agent_->vrf_table();
793 12 : VrfEntry *vrf = static_cast<VrfEntry *> (table->Find(entry));
794 12 : FreeVrfState(vrf, gen_id);
795 12 : return true;
796 : }
797 :
798 131 : if (dynamic_cast<const AgentRoute *>(entry)) {
799 131 : VrfEntry *vrf = (static_cast<const AgentRoute *>(entry))->vrf();
800 131 : AgentRoute *rt = NULL;
801 131 : if (dynamic_cast<const InetUnicastRouteEntry *>(entry)) {
802 79 : DBTable *table = NULL;
803 79 : if ((dynamic_cast<const AgentRoute *>(entry))->GetTableType()
804 79 : == Agent::INET4_UNICAST)
805 55 : table = vrf->GetInet4UnicastRouteTable();
806 : else
807 24 : table = vrf->GetInet6UnicastRouteTable();
808 79 : rt = static_cast<AgentRoute *>(table->Find(entry));
809 : } else {
810 52 : DBTable *table = vrf->GetBridgeRouteTable();
811 52 : rt = static_cast<AgentRoute *>(table->Find(entry));
812 : }
813 131 : FreeRouteState(rt, gen_id);
814 131 : return true;
815 : }
816 :
817 0 : assert(0);
818 : return true;
819 : }
|