OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mac_learning_db_client.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
3  */
5 #include "mac_learning_init.h"
6 #include "mac_learning_proto.h"
8 #include "mac_learning.h"
9 #include "mac_learning_mgmt.h"
10 #include "mac_aging.h"
11 
13  agent_(agent), interface_listener_id_(), vrf_listener_id_(),
14  vn_listener_id_(), hc_listener_id_() {
15 }
16 
19  (boost::bind(&MacLearningDBClient::InterfaceNotify, this, _1, _2));
21  (boost::bind(&MacLearningDBClient::VrfNotify, this, _1, _2));
23  (boost::bind(&MacLearningDBClient::VnNotify, this, _1, _2));
25  (boost::bind(&MacLearningDBClient::HealthCheckNotify, this, _1, _2));
26 }
27 
33 }
34 
36 }
37 
39  Interface *intf = static_cast<Interface *>(e);
40  if (intf->type() != Interface::VM_INTERFACE) {
41  return;
42  }
43 
44  MacLearningIntfState *state = static_cast<MacLearningIntfState *>
45  (e->GetState(part->parent(), interface_listener_id_));
46 
47  VmInterface *vm_port = static_cast<VmInterface *>(intf);
48  if (intf->IsDeleted()) {
49  if (state) {
50  DeleteEvent(vm_port, state);
51  }
52  return;
53  }
54 
55  bool changed = false;
56  bool delete_mac = false;
57  if (state == NULL) {
58  state = new MacLearningIntfState();
59  e->SetState(part->parent(), interface_listener_id_, state);
60  state->l2_label_ = vm_port->l2_label();
61  state->sg_l_ = vm_port->sg_list();
62  state->learning_enabled_ = vm_port->learning_enabled();
63  state->policy_enabled_ = vm_port->policy_enabled();
64  state->l2_active_ = vm_port->IsL2Active();
65  changed = true;
66  e->SetState(part->parent(), interface_listener_id_, state);
67  } else {
68  if (state->deleted_ == true) {
69  state->deleted_ = false;
70  changed = true;
71  }
72 
73  if (state->l2_label_ != vm_port->l2_label()) {
74  state->l2_label_ = vm_port->l2_label();
75  changed = true;
76  }
77 
78  const VmInterface::SecurityGroupEntryList &new_sg_l = vm_port->sg_list();
79  if (state->sg_l_.list_ != new_sg_l.list_) {
80  state->sg_l_ = new_sg_l;
81  changed = true;
82  }
83 
84  if (state->learning_enabled_ != vm_port->learning_enabled()) {
85  state->learning_enabled_ = vm_port->learning_enabled();
86  if (state->learning_enabled_ == false) {
87  delete_mac = true;
88  }
89  }
90 
91  if (state->policy_enabled_ != vm_port->policy_enabled()) {
92  state->policy_enabled_ = vm_port->policy_enabled();
93  changed = true;
94  }
95 
96  if (state->l2_active_ != vm_port->IsL2Active()) {
97  state->l2_active_ = vm_port->IsL2Active();
98  if (state->l2_active_ == false) {
99  delete_mac = true;
100  }
101  }
102  }
103 
104  if (delete_mac) {
105  DeleteAllMac(vm_port, state);
106  return;
107  }
108 
109  if (changed) {
110  AddEvent(vm_port, state);
111  }
112 }
113 
115  VnEntry *vn = static_cast<VnEntry *>(e);
116 
117  MacLearningVnState *state = static_cast<MacLearningVnState *>
118  (e->GetState(part->parent(), vn_listener_id_));
119 
120  if (vn->IsDeleted()) {
121  if (state) {
122  DeleteEvent(vn, state);
123  }
124  return;
125  }
126 
127  bool changed = false;
128  bool delete_mac_ip = false;
129  if (state == NULL) {
130  state = new MacLearningVnState();
131  e->SetState(part->parent(), vn_listener_id_, state);
133  state->hc_uuid_ = vn->health_check_uuid();
134  changed = true;
135  } else {
136  if (state->mac_ip_learning_enabled_ != vn->mac_ip_learning_enable()) {
138  if (state->mac_ip_learning_enabled_ == false) {
139  delete_mac_ip = true;
140  }
141  }
142  if (state->hc_uuid_ != vn->health_check_uuid()) {
143  state->hc_uuid_ = vn->health_check_uuid();
144  changed = true;
145  }
146 
147  }
148 
149  if (delete_mac_ip) {
150  DeleteAllMac(vn, state);
151  return;
152  }
153 
154  if (changed) {
155  AddEvent(vn, state);
156  }
157 }
158 
160  HealthCheckService *hc_service = static_cast<HealthCheckService *>(e);
161 
163  (e->GetState(part->parent(), hc_listener_id_));
164 
165  if (hc_service->IsDeleted()) {
166  if (state) {
167  DeleteNoOpEvent(hc_service, state);
168  }
169  return;
170  }
171  bool param_changed = false;
172  bool ip_list_changed = false;
173  if (state == NULL) {
174  state = new MacLearningHealthCheckState();
175  e->SetState(part->parent(), hc_listener_id_, state);
176  state->delay_ = hc_service->delay();
177  state->delay_usecs_ = hc_service->delay_usecs();
178  state->timeout_ = hc_service->timeout();
179  state->timeout_usecs_ = hc_service->timeout_usecs();
180  state->max_retries_ = hc_service->max_retries();
182  hc_service->IsHcEnableAllTargetIp();
183  state->hc_target_ip_list_ = hc_service->GetTargetIpList();
184  param_changed = true;
185  } else {
186  if (state->delay_ != hc_service->delay()) {
187  state->delay_ = hc_service->delay();
188  param_changed = true;
189  }
190  if (state->delay_usecs_ != hc_service->delay_usecs()) {
191  state->delay_usecs_ = hc_service->delay_usecs();
192  param_changed = true;
193  }
194  if (state->timeout_ != hc_service->timeout()) {
195  state->timeout_ = hc_service->timeout();
196  param_changed = true;
197  }
198  if (state->timeout_usecs_ != hc_service->timeout_usecs()) {
199  state->timeout_usecs_ = hc_service->timeout_usecs();
200  param_changed = true;
201  }
202  if (state->max_retries_ != hc_service->max_retries()) {
203  state->max_retries_ = hc_service->max_retries();
204  param_changed = true;
205  }
206  if (state->is_hc_enable_all_target_ips !=
207  hc_service->IsHcEnableAllTargetIp()) {
209  hc_service->IsHcEnableAllTargetIp();
210  ip_list_changed = true;
211  }
212  if (state->hc_target_ip_list_ != hc_service->GetTargetIpList()) {
213  state->hc_target_ip_list_ = hc_service->GetTargetIpList();
214  ip_list_changed = true;
215  }
216  }
217  if (param_changed) {
218  AddEvent(hc_service, state);
219  }
220  if (ip_list_changed) {
221  std::set<boost::uuids::uuid> vn_uuid_list = hc_service->GetVnUuidList();
222  std::set<boost::uuids::uuid>::iterator it = vn_uuid_list.begin();
223  while(it != vn_uuid_list.end()) {
224  VnEntry *vn = agent_->vn_table()->Find(*it);
225  if (vn && !vn->IsDeleted()) {
226  MacLearningVnState *state = static_cast<MacLearningVnState *>
227  (vn->GetState(vn->get_table(), vn_listener_id_));
228  if (state) {
229  AddEvent(vn, state);
230  }
231  }
232  it++;
233  }
234  }
235 }
236 
237 
240  DBTablePartBase *partition,
241  DBEntryBase *e) {
243  MacLearningRouteState *rt_state =
244  static_cast<MacLearningRouteState *>(e->GetState(partition->parent(),
245  vrf_state->bridge_listener_id_));
246  AgentRoute *route = static_cast<AgentRoute *>(e);
247 
248  ReleaseToken(route);
249 
250  if (route->IsDeleted() && route->is_multicast() == false) {
251  if (vrf_state && rt_state) {
252  rt_state->gen_id_++;
253  DeleteEvent(route, rt_state);
254  }
255  return;
256  }
257 
258  if (vrf_state->deleted_) {
259  // ignore route add/change for delete notified VRF.
260  return;
261  }
262 
263  if (route->is_multicast()) {
264  return;
265  }
266 
267  if (rt_state == NULL) {
268  rt_state = new MacLearningRouteState();
269  route->SetState(partition->parent(), id, rt_state);
270  AddEvent(route, rt_state);
271  } else {
272  ChangeEvent(route, rt_state);
273  }
274 }
275 
278  DBTablePartBase *partition,
279  DBEntryBase *e) {
280  AgentRoute *route = static_cast<AgentRoute *>(e);
281 
282  if (route->IsDeleted()) {
283  return;
284  }
285 
286  if (vrf_state->deleted_) {
287  // ignore route add/change for delete notified VRF.
288  return;
289  }
290 
291  if (route->is_multicast()) {
292  return;
293  }
294 
295  EvpnRouteEntry *entry = dynamic_cast<EvpnRouteEntry *>(route);
296  if (!entry) {
297  return;
298  }
299 
300  if (!entry->IsType2()) {
301  return;
302  }
303  if (route->FindLocalVmPortPath()) {
304  return;
305  }
306 
307  IpAddress ip_ = entry->prefix_address();
308  MacAddress mac_ = entry->mac();
311  entry->vrf_id(),
312  ip_,
313  mac_));
314 
316  GetMacIpLearningTable()->Enqueue(ptr);
317 
318 }
320  VrfEntry *vrf) {
321  // Register to the Bridge Unicast Table
322  BridgeAgentRouteTable *bridge_table = static_cast<BridgeAgentRouteTable *>
323  (vrf->GetBridgeRouteTable());
325  bridge_table->Register(boost::bind(&MacLearningDBClient::RouteNotify,
326  client, this, Agent::BRIDGE, _1,
327  _2));
328  // Register to the EVPN Table
329  EvpnAgentRouteTable *evpn_table = static_cast<EvpnAgentRouteTable *>
330  (vrf->GetEvpnRouteTable());
332  evpn_table->Register(boost::bind(&MacLearningDBClient::EvpnRouteNotify,
333  client, this, Agent::EVPN, _1,
334  _2));
335 }
336 
338  BridgeAgentRouteTable *bridge_table = static_cast<BridgeAgentRouteTable *>
339  (vrf->GetBridgeRouteTable());
340  bridge_table->Unregister(bridge_listener_id_);
341  // Register to the EVPN Table
342  EvpnAgentRouteTable *evpn_table = static_cast<EvpnAgentRouteTable *>
343  (vrf->GetEvpnRouteTable());
344  evpn_table->Unregister(evpn_listener_id_);
345 }
346 
348  VrfEntry *vrf = static_cast<VrfEntry *>(e);
349 
350  MacLearningVrfState *state = static_cast<MacLearningVrfState *>
351  (e->GetState(part->parent(), vrf_listener_id_));
352 
353  if (vrf->IsDeleted()) {
354  if (state) {
355  DeleteEvent(vrf, state);
356  }
357  return;
358  }
359 
360  if (state == NULL) {
361  state = new MacLearningVrfState();
362  e->SetState(part->parent(), vrf_listener_id_, state);
363  state->Register(this, vrf);
364  state->isid_ = vrf->isid();
365  AddEvent(vrf, state);
366  }
367 
368  if (state->learning_enabled_ != vrf->learning_enabled()) {
369  state->learning_enabled_ = vrf->learning_enabled();
370  if (state->learning_enabled_ == false) {
371  DeleteAllMac(vrf, state);
372  }
373  }
374 
375  if (state->isid_ != vrf->isid()) {
376  state->isid_ = vrf->isid();
377  DeleteAllMac(vrf, state);
378  }
379 }
380 
381 void MacLearningDBClient::FreeRouteState(const DBEntry *ce, uint32_t gen_id) {
382  DBEntry *e = const_cast<DBEntry *>(ce);
383  AgentRoute *rt = static_cast<AgentRoute *>(e);
384  if (rt->IsDeleted() == false) {
385  return;
386  }
387 
388  VrfEntry *vrf = rt->vrf();
389  MacLearningVrfState *vrf_state = static_cast<MacLearningVrfState *>
390  (vrf->GetState(vrf->get_table(), vrf_listener_id_));
391  if (vrf_state == NULL) {
392  return;
393  }
394 
395  MacLearningRouteState *state =
396  static_cast<MacLearningRouteState *>(rt->GetState(rt->get_table(),
397  vrf_state->bridge_listener_id_));
398  if (state->gen_id_ != gen_id) {
399  return;
400  }
401 
402  rt->ClearState(rt->get_table(), vrf_state->bridge_listener_id_);
403  delete state;
404 }
405 
408  for (uint32_t i = 0; i < ml_proto->size(); i++) {
411  ml_proto->Find(i)->aging_partition()->Enqueue(ptr);
412  }
413 }
414 
415 void MacLearningDBClient::FreeDBState(const DBEntry *entry, uint32_t gen_id) {
416  if (dynamic_cast<const Interface *>(entry)) {
417  DBTable *table = agent_->interface_table();
418  Interface *intf = static_cast<Interface *>(table->Find(entry));
419  DBState *state = intf->GetState(intf->get_table(),
422  delete state;
423  return;
424  }
425 
426  if (dynamic_cast<const VrfEntry *>(entry)) {
427  //Enqueue request to delete aging table pointers
428  DBTable *table = agent_->vrf_table();
429  VrfEntry *vrf = static_cast<VrfEntry *>(table->Find(entry));
430 
432 
433  DBState *state = vrf->GetState(vrf->get_table(),
435  MacLearningVrfState *vrf_state =
436  static_cast<MacLearningVrfState *>(state);
437  vrf->ClearState(vrf->get_table(), vrf_listener_id_);
438  vrf_state->Unregister(vrf);
439  delete state;
440  return;
441  }
442 
443  if (dynamic_cast<const AgentRoute *>(entry)) {
444  FreeRouteState(entry, gen_id);
445  return;
446  }
447  if (dynamic_cast<const VnEntry *>(entry)) {
448  DBTable *table = agent_->vn_table();
449  VnEntry *vn = static_cast<VnEntry *>(table->Find(entry));
450  DBState *state = vn->GetState(vn->get_table(),
453  delete state;
454  return;
455  }
456  if (dynamic_cast<const HealthCheckService *>(entry)) {
457  DBTable *table = agent_->health_check_table();
458  HealthCheckService *hc = static_cast<HealthCheckService *>(table->Find(entry));
459  DBState *state = hc->GetState(hc->get_table(),
462  delete state;
463  return;
464  }
465 }
466 
468  MacLearningDBState *state) {
472 }
473 
475  MacLearningDBState *state) {
479 }
480 
482  MacLearningDBState *state) {
485  state->gen_id_));
487 }
488 // this event does not trigger macip entry delete event, it marks
489 // maclearningdbentry as deleted. this is needed for cases where
490 // dependent entries are interested only add/update events.
492  MacLearningDBState *state) {
495  state->gen_id_));
497 }
501  state->gen_id_));
503 }
504 
506  const BridgeRouteEntry *brt =
507  dynamic_cast<const BridgeRouteEntry *>(entry);
508 
509  //Get the partition id for mac of interest
510  uint32_t id = agent_->mac_learning_proto()->Hash(brt->vrf()->vrf_id(),
511  brt->prefix_address());
512  MacLearningPartition *partition =
514  assert(partition);
515 
516  //Release the token
517  MacLearningKey key(brt->vrf()->vrf_id(), brt->prefix_address());
518  partition->ReleaseToken(key);
519 }
void Enqueue(MacLearningMgmtRequestPtr &ptr)
uint32_t vrf_id() const
AgentPath * FindLocalVmPortPath() const
Definition: agent_route.cc:742
void RouteNotify(MacLearningVrfState *state, Agent::RouteTableType type, DBTablePartBase *partition, DBEntryBase *e)
Type type() const
Definition: interface.h:112
void DeleteAllMac(const DBEntry *entry, MacLearningDBState *state)
bool mac_ip_learning_enable() const
Definition: vn.h:238
Definition: vrf.h:86
AgentRouteTable * GetEvpnRouteTable() const
Definition: vrf.cc:330
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
Definition: db_entry.cc:37
MacAgingPartition * aging_partition() const
Definition: mac_learning.h:231
MacLearningPartition * Find(uint32_t index)
boost::shared_ptr< MacLearningMgmtRequest > MacLearningMgmtRequestPtr
DBTableBase::ListenerId interface_listener_id_
DBTableBase * get_table() const
Definition: db_entry.cc:119
bool IsDeleted() const
Definition: db_entry.h:49
DBTableBase::ListenerId vrf_listener_id_
void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state)
Definition: db_entry.cc:22
void VnNotify(DBTablePartBase *part, DBEntryBase *e)
boost::asio::ip::address IpAddress
Definition: address.h:13
MacLearningProto * mac_learning_proto() const
Definition: agent.h:1005
VmInterface::SecurityGroupEntryList sg_l_
int ListenerId
Definition: db_table.h:62
bool is_multicast() const
Definition: agent_route.h:274
void DeleteNoOpEvent(const DBEntry *entry, MacLearningDBState *state)
DBTableBase * parent()
void EvpnRouteNotify(MacLearningVrfState *state, Agent::RouteTableType type, DBTablePartBase *partition, DBEntryBase *e)
InterfaceTable * interface_table() const
Definition: agent.h:465
MacLearningModule * mac_learning_module() const
Definition: agent.h:1013
VnTable * vn_table() const
Definition: agent.h:495
Base class for all Route entries in agent.
Definition: agent_route.h:224
void Unregister(ListenerId listener)
Definition: db_table.cc:186
bool learning_enabled() const
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
Definition: db_table.cc:181
uint32_t timeout() const
Definition: health_check.h:332
bool learning_enabled() const
Definition: vrf.h:128
const SecurityGroupEntryList & sg_list() const
uint8_t type
Definition: load_balance.h:109
void AddEvent(const DBEntry *entry, MacLearningDBState *state)
Definition: agent.h:358
void FreeDBState(const DBEntry *db_entry, uint32_t gen_id)
void InterfaceNotify(DBTablePartBase *part, DBEntryBase *e)
const std::set< boost::uuids::uuid > & GetVnUuidList()
Definition: health_check.h:344
bool IsHcEnableAllTargetIp() const
Definition: health_check.h:359
void DeleteEvent(const DBEntry *entry, MacLearningDBState *state)
bool Enqueue(PktInfoPtr msg)
AgentRouteTable * GetBridgeRouteTable() const
Definition: vrf.cc:334
void VrfNotify(DBTablePartBase *part, DBEntryBase *e)
boost::shared_ptr< MacLearningEntryRequest > MacLearningEntryRequestPtr
bool policy_enabled() const
void Enqueue(MacLearningEntryRequestPtr req)
Definition: mac_aging.cc:194
const uint32_t vrf_id() const
Definition: vrf.h:99
VnEntry * Find(const boost::uuids::uuid &vn_uuid)
Definition: vn.cc:759
void ClearState(DBTableBase *tbl_base, ListenerId listener)
Definition: db_entry.cc:73
const MacAddress & mac() const
void ReleaseToken(const MacLearningKey &key)
virtual const PrefixType & prefix_address() const
Returns the value of a stored prefix address (IPv4, IPv6 or MAC address)
Definition: agent_route.h:375
uint32_t isid() const
Definition: vrf.h:197
void ReleaseToken(const DBEntry *entry)
Definition: vn.h:151
void ChangeEvent(const DBEntry *entry, MacLearningDBState *state)
VrfTable * vrf_table() const
Definition: agent.h:485
HealthCheckTable * health_check_table() const
Definition: agent.cc:933
const boost::uuids::uuid & health_check_uuid() const
Definition: vn.h:242
const std::set< IpAddress > & GetTargetIpList()
Definition: health_check.h:347
uint32_t delay() const
Definition: health_check.h:330
uint32_t l2_label() const
Definition: interface.h:128
void EnqueueAgingTableDelete(const VrfEntry *vrf)
DBEntry * Find(const DBEntry *entry)
Definition: db_table.cc:469
uint32_t max_retries() const
Definition: health_check.h:334
VrfEntry * vrf() const
Definition: agent_route.h:275
uint64_t delay_usecs() const
Definition: health_check.h:331
RouteTableType
Definition: agent.h:415
uint32_t Hash(uint32_t vrf_id, const MacAddress &mac)
DBTableBase::ListenerId hc_listener_id_
bool IsL2Active() const
void FreeRouteState(const DBEntry *e, uint32_t gen_id)
void HealthCheckNotify(DBTablePartBase *part, DBEntryBase *e)
MacLearningMgmtManager * mac_learning_mgmt() const
void Register(MacLearningDBClient *client, VrfEntry *vrf)
DBTableBase::ListenerId vn_listener_id_
uint64_t timeout_usecs() const
Definition: health_check.h:333