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