OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
multicast_mac_local_ovsdb.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 extern "C" {
6 #include <ovsdb_wrapper.h>
7 };
8 #include <cmn/agent.h>
9 #include <oper/vn.h>
10 #include <oper/vrf.h>
11 #include <oper/vxlan.h>
14 #include <ovsdb_client.h>
15 #include <ovsdb_client_idl.h>
16 #include <ovsdb_client_session.h>
17 #include <base/util.h>
18 #include <base/string_util.h>
19 #include <oper/agent_sandesh.h>
20 #include <ovsdb_sandesh.h>
21 #include <ovsdb_types.h>
22 #include <ovsdb_route_peer.h>
23 #include <logical_switch_ovsdb.h>
25 #include <vn_ovsdb.h>
26 
27 using namespace OVSDB;
28 using std::string;
29 
31  const MulticastMacLocalEntry *key) : OvsdbEntry(table),
32  logical_switch_name_(key->logical_switch_name_), vrf_(NULL, this),
33  vxlan_id_(key->vxlan_id_), row_list_(key->row_list_) {
34 }
35 
37  const std::string &logical_switch_name)
38  : OvsdbEntry(table), logical_switch_name_(logical_switch_name),
39  vrf_(NULL, this), vxlan_id_(0), row_list_() {
40 }
41 
43  const std::string &logical_switch_name, struct ovsdb_idl_row *row)
44  : OvsdbEntry(table), logical_switch_name_(logical_switch_name),
45  vrf_(NULL, this), vxlan_id_(0), row_list_() {
46  if (row) {
47  row_list_.insert(row);
48  }
49 }
50 
52  VnOvsdbObject *vn_object = table_->client_idl()->vn_ovsdb();
54  VnOvsdbEntry *vn_entry =
55  static_cast<VnOvsdbEntry *>(vn_object->GetReference(&vn_key));
56  return vn_entry;
57 }
58 
60  OVSDB::VnOvsdbEntry *vn_entry = GetVnEntry();
61  if ((vn_entry == NULL) || (vn_entry->vrf() == NULL)) {
62  OnVrfDelete();
63  // Issue a ADD_CHANGE_REQ to push entry into defer state.
64  // Whenever VN entry is back this will be updated.
66  }
67 }
68 
70  if (vrf_ == NULL)
71  return;
72 
73  MulticastMacLocalOvsdb *table = static_cast<MulticastMacLocalOvsdb *>(table_);
74  OVSDB_TRACE(Trace, "Deleting Multicast Route VN uuid " + logical_switch_name_);
75  TorIpList::iterator it_ip = tor_ip_list_.begin();
76  for (; it_ip != tor_ip_list_.end(); it_ip++) {
78  (*it_ip));
79  }
80  tor_ip_list_.clear();
82  this));
83  // remove vrf reference after deleting route
84  vrf_ = NULL;
85  return;
86 }
87 
89  OvsdbIdlRowList::iterator it = row_list_.begin();
90  TorIpList old_tor_ip_list = tor_ip_list_;
91  uint32_t old_vxlan_id = vxlan_id_;
92  // clear the list to hold new entries
93  tor_ip_list_.clear();
94 
95  MulticastMacLocalOvsdb *table = static_cast<MulticastMacLocalOvsdb *>(table_);
96 
97  OVSDB::VnOvsdbEntry *vn_entry = GetVnEntry();
98  // Take vrf reference to genrate withdraw/delete route request
99  vrf_ = vn_entry->vrf();
100  OVSDB_TRACE(Trace, "Adding multicast Route VN uuid " + logical_switch_name_);
101  vxlan_id_ = vn_entry->vxlan_id();
102 
103  //In case vxlan id is changed then remove old vaxlan id before auditing
104  //list.
105  if (old_vxlan_id != vxlan_id_) {
106  TorIpList::iterator it_ip = old_tor_ip_list.begin();
107  for (; it_ip != old_tor_ip_list.end(); it_ip++) {
108  table->peer()->DeleteOvsPeerMulticastRoute(vrf_.get(), old_vxlan_id,
109  (*it_ip));
110  }
111  //No need of old list, so flush it and honor new list
112  old_tor_ip_list.clear();
113  }
114 
116  this));
117 
118  for (; it != row_list_.end(); it++) {
119  struct ovsdb_idl_row *l_set =
121  std::size_t count =
123  for (std::size_t i = 0; i != count; i++) {
124  struct ovsdb_idl_row *locator =
126  std::string tor_ip_str =
128  boost::system::error_code ec;
129  Ip4Address tor_ip = Ip4Address::from_string(tor_ip_str, ec);
130  if (tor_ip.to_ulong() == 0) {
131  // 0 ip is not valid ip to export, continue to next row
132  continue;
133  }
134  // insert the current ip to new list
135  tor_ip_list_.insert(tor_ip);
136  // remove from the old list
137  old_tor_ip_list.erase(tor_ip);
138 
139  // export the OVS route to Oper Db
140  table->peer()->AddOvsPeerMulticastRoute(vrf_.get(), vxlan_id_,
141  vn_entry->name(),
142  table_->client_idl()->tsn_ip(),
143  tor_ip);
144  }
145  }
146 
147  TorIpList::iterator it_ip = old_tor_ip_list.begin();
148  for (; it_ip != old_tor_ip_list.end(); it_ip++) {
150  (*it_ip));
151  }
152 
153  return true;
154 }
155 
157  return Add();
158 }
159 
161  OnVrfDelete();
162  return true;
163 }
164 
165 bool MulticastMacLocalEntry::IsLess(const KSyncEntry& entry) const {
166  const MulticastMacLocalEntry &mcast =
167  static_cast<const MulticastMacLocalEntry&>(entry);
169 }
170 
172  VnOvsdbEntry *vn_entry = GetVnEntry();
173  if (!vn_entry->IsResolved()) {
174  OVSDB_TRACE(Trace, "Skipping multicast route add " +
175  logical_switch_name_ + " due to unavailable VN ");
176  return vn_entry;
177  }
178 
179  return NULL;
180 }
181 
184  return tor_ip_list_;
185 }
186 
188  return logical_switch_name_;
189 }
190 
192  OvsdbObject(idl), peer_(peer) {
194  idl->agent()->task_scheduler()->GetTaskId("Agent::KSync"), 0,
195  boost::bind(&MulticastMacLocalOvsdb::VrfReEval, this, _1));
196  vrf_reeval_queue_->set_name("OVSDB VRF Multicast local mac re-evaluation "
197  "queue");
198  // register to listen updates for multicast mac local
200  boost::bind(&MulticastMacLocalOvsdb::Notify, this, _1, _2));
201  // registeration to physical locator set is also required, since
202  // an update for physical locators in the set can show up after
203  // multicast row update // during which we need to trigger
204  // re-evaluation of the exported multicast route
206  boost::bind(&MulticastMacLocalOvsdb::LocatorSetNotify, this,
207  _1, _2));
208 }
209 
211  vrf_reeval_queue_->Shutdown();
212  delete vrf_reeval_queue_;
213 }
214 
216  return peer_;
217 }
218 
220  vrf_reeval_queue_->Enqueue(vrf);
221 }
222 
223 //Only executed for VRF delete
225  // iterate through dependency list and trigger del and add
226  VrfDepList::iterator it =
227  vrf_dep_list_.upper_bound(VrfDepEntry(vrf_ref.get(), NULL));
228  while (it != vrf_dep_list_.end()) {
229  if (it->first != vrf_ref.get()) {
230  break;
231  }
232  MulticastMacLocalEntry *m_entry = it->second;
233  it++;
234  m_entry->EvaluateVrfDependency(vrf_ref.get());
235  }
236  return true;
237 }
238 
240  struct ovsdb_idl_row *row) {
241  const char *ls_name = ovsdb_wrapper_mcast_mac_local_logical_switch(row);
242 
243  LogicalSwitchTable *l_table = client_idl_->logical_switch_table();
244  l_table->OvsdbMcastLocalMacNotify(op, row);
245 
246  /* ignore if ls_name is not present */
247  if (ls_name == NULL) {
248  return;
249  }
250 
251  std::string ls_name_str(ls_name);
252  MulticastMacLocalEntry key(this, ls_name, row);
253  MulticastMacLocalEntry *entry =
254  static_cast<MulticastMacLocalEntry*>(FindActiveEntry(&key));
255  struct ovsdb_idl_row *l_set =
257  // physical locator set is immutable so it will not change
258  // for given multicast row, trigger delete for row and
259  // wait for locator set to be available
260  if (op == OvsdbClientIdl::OVSDB_DEL || l_set == NULL) {
261  if (entry != NULL) {
262  entry->row_list_.erase(row);
263  if (l_set != NULL) {
264  locator_dep_list_.erase(l_set);
265  }
266  if (entry->row_list_.empty()) {
267  // delete entry if the last idl row is removed
268  Delete(entry);
269  } else {
270  // trigger change on entry to remove the delete ToR IP
271  // from the list
272  Change(entry);
273  }
274  }
275  } else if (op == OvsdbClientIdl::OVSDB_ADD) {
276  if (entry == NULL) {
277  entry = static_cast<MulticastMacLocalEntry*>(Create(&key));
278  } else {
279  entry->row_list_.insert(row);
280  // trigger change on entry to add the new ToR IP
281  // to the list
282  Change(entry);
283  }
284  locator_dep_list_[l_set] = entry;
285  }
286 }
287 
289  struct ovsdb_idl_row *row) {
290  if (op == OvsdbClientIdl::OVSDB_DEL) {
291  locator_dep_list_.erase(row);
292  return;
293  }
294  OvsdbIdlDepList::iterator it = locator_dep_list_.find(row);
295  if (it != locator_dep_list_.end()) {
296  Change(it->second);
297  }
298 }
299 
301  const MulticastMacLocalEntry *k_entry =
302  static_cast<const MulticastMacLocalEntry *>(key);
303  MulticastMacLocalEntry *entry = new MulticastMacLocalEntry(this, k_entry);
304  return entry;
305 }
306 
308 // Sandesh routines
311  std::string resp_ctx, AgentSandeshArguments &args) :
312  OvsdbSandeshTask(resp_ctx, args) {
313  if (args.Get("ls_name", &ls_name_) == false) {
314  ls_name_ = "";
315  }
316 }
317 
319  std::string resp_ctx, const std::string &ip, uint32_t port,
320  const std::string &ls) :
321  OvsdbSandeshTask(resp_ctx, ip, port), ls_name_(ls) {
322 }
323 
325 }
326 
328  if (!ls_name_.empty()) {
329  args.Add("ls_name", ls_name_);
330  }
331 }
332 
335  if (!ls_name_.empty()) {
336  MulticastMacLocalEntry *entry =
337  static_cast<MulticastMacLocalEntry *>(kentry);
338  if (entry->logical_switch_name().find(ls_name_) != std::string::npos) {
339  return FilterAllow;
340  }
341  return FilterDeny;
342  }
343  return FilterAllow;
344 }
345 
347  SandeshResponse *resp) {
348  MulticastMacLocalEntry *entry =
349  static_cast<MulticastMacLocalEntry *>(kentry);
350  OvsdbMulticastMacLocalEntry oentry;
351  oentry.set_state(entry->StateString());
352  oentry.set_mac("ff:ff:ff:ff:ff:ff");
353  oentry.set_logical_switch(entry->logical_switch_name());
354  oentry.set_vxlan_id(entry->vxlan_id());
355  std::vector<std::string> &tor_ip =
356  const_cast<std::vector<std::string>&>(oentry.get_tor_ip());
357  MulticastMacLocalEntry::TorIpList::const_iterator it =
358  entry->tor_ip_list().begin();
359  for (; it != entry->tor_ip_list().end(); it++) {
360  tor_ip.push_back((*it).to_string());
361  }
362  OvsdbMulticastMacLocalResp *m_resp =
363  static_cast<OvsdbMulticastMacLocalResp *>(resp);
364  std::vector<OvsdbMulticastMacLocalEntry> &macs =
365  const_cast<std::vector<OvsdbMulticastMacLocalEntry>&>(
366  m_resp->get_macs());
367  macs.push_back(oentry);
368 }
369 
371  return static_cast<SandeshResponse *>(new OvsdbMulticastMacLocalResp());
372 }
373 
375  OvsdbClientSession *session) {
376  return static_cast<KSyncObject *>(
377  session->client_idl()->multicast_mac_local_ovsdb());
378 }
379 
380 void OvsdbMulticastMacLocalReq::HandleRequest() const {
382  new MulticastMacLocalSandeshTask(context(), get_session_remote_ip(),
383  get_session_remote_port(),
384  get_logical_switch());
386  scheduler->Enqueue(task);
387 }
uint32_t vxlan_id()
Definition: vn_ovsdb.h:44
#define OVSDB_TRACE(obj,...)
void Change(KSyncEntry *entry)
char * ovsdb_wrapper_mcast_mac_local_logical_switch(struct ovsdb_idl_row *row)
static boost::uuids::uuid StringToUuid(const std::string &str)
Definition: string_util.h:145
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
Definition: vrf.h:86
const TorIpList & tor_ip_list() const
MulticastMacLocalEntry(MulticastMacLocalOvsdb *table, const MulticastMacLocalEntry *key)
bool IsResolved()
MulticastMacLocalSandeshTask(std::string resp_ctx, AgentSandeshArguments &args)
char * ovsdb_wrapper_physical_locator_dst_ip(struct ovsdb_idl_row *row)
void EncodeArgs(AgentSandeshArguments &args)
void UpdateResp(KSyncEntry *kentry, SandeshResponse *resp)
std::string StateString() const
const std::string & logical_switch_name() const
struct ovsdb_idl_row * ovsdb_wrapper_mcast_mac_local_physical_locator_set(struct ovsdb_idl_row *row)
void Delete(KSyncEntry *entry)
Agent * agent() const
bool IsLess(const KSyncEntry &) const
void Notify(OvsdbClientIdl::Op op, struct ovsdb_idl_row *row)
void Register(EntryType type, NotifyCB cb)
MulticastMacLocalOvsdb * multicast_mac_local_ovsdb()
WorkQueue< VrfEntryRef > * vrf_reeval_queue_
OVSDB::VnOvsdbEntry * GetVnEntry() const
int GetTaskId(const std::string &name)
Definition: task.cc:856
KSyncEntry * FindActiveEntry(KSyncEntry *key)
Definition: ovsdb_object.cc:23
VnOvsdbObject * vn_ovsdb()
TaskScheduler * task_scheduler() const
Definition: agent.h:1120
bool Get(const std::string &key, std::string *val) const
void SafeNotifyEvent(KSyncEntry *entry, KSyncEntry::KSyncEvent event)
static TaskScheduler * GetInstance()
Definition: task.cc:547
void Enqueue(Task *task)
Enqueues a task for running. Starts task if all policy rules are met else puts task in waitq...
Definition: task.cc:636
struct ovsdb_idl_row ** ovsdb_wrapper_physical_locator_set_locators(struct ovsdb_idl_row *row)
Definition: trace.h:220
bool Add(const std::string &key, const std::string &val)
KSyncEntry * GetReference(const KSyncEntry *key)
void OvsdbMcastLocalMacNotify(OvsdbClientIdl::Op, struct ovsdb_idl_row *)
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
std::pair< VrfEntry *, MulticastMacLocalEntry * > VrfDepEntry
KSyncEntry * Create(const KSyncEntry *key)
KSyncObject * GetObject(OvsdbClientSession *session)
void AddOvsPeerMulticastRoute(const VrfEntry *vrf, uint32_t vxlan_id, const std::string &vn_name_, const Ip4Address &tsn_ip, const Ip4Address &tor_ip)
OvsdbObject * table_
Definition: ovsdb_entry.h:52
KSyncEntry * Alloc(const KSyncEntry *key, uint32_t index)
OvsdbClientIdlPtr client_idl_
Definition: ovsdb_object.h:34
const std::string & name()
Definition: vn_ovsdb.h:45
VrfEntry * vrf()
Definition: vn_ovsdb.cc:92
void DeleteOvsPeerMulticastRoute(const VrfEntry *vrf, uint32_t vxlan_id, const Ip4Address &tor_ip)
size_t ovsdb_wrapper_physical_locator_set_locator_count(struct ovsdb_idl_row *row)
struct task_ task
MulticastMacLocalOvsdb(OvsdbClientIdl *idl, OvsPeer *peer)
void LocatorSetNotify(OvsdbClientIdl::Op op, struct ovsdb_idl_row *row)
OvsdbClientIdl * client_idl()
Definition: ovsdb_object.h:31