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