OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
physical_port_ovsdb.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 extern "C" {
6 #include <ovsdb_wrapper.h>
7 };
8 
9 #include <base/task.h>
10 
12 #include <ovsdb_client.h>
13 #include <ovsdb_client_idl.h>
14 #include <ovsdb_client_session.h>
15 
16 #include <logical_switch_ovsdb.h>
17 #include <physical_port_ovsdb.h>
19 #include <ovsdb_sandesh.h>
20 #include <ovsdb_types.h>
21 
22 using namespace OVSDB;
23 
25  const std::string &dev_name, const std::string &name) :
26  OvsdbEntry(table), name_(name), dev_name_(dev_name), binding_table_(),
27  ovs_binding_table_() {
28 }
29 
31 }
32 
34  if (ovs_entry_ == NULL) {
35  return true;
36  }
37 
38  return OverrideOvs();
39 }
40 
42  return Add();
43 }
44 
46  // Nothing to do on delete, return true and be done
47  return true;
48 }
49 
50 bool PhysicalPortEntry::IsLess(const KSyncEntry &entry) const {
51  const PhysicalPortEntry &ps_entry =
52  static_cast<const PhysicalPortEntry&>(entry);
53  if (dev_name_ != ps_entry.dev_name_) {
54  return (dev_name_.compare(ps_entry.dev_name_) < 0);
55  }
56 
57  return (name_.compare(ps_entry.name_) < 0);
58 }
59 
61  return NULL;
62 }
63 
65  if (!IsResolved()) {
66  /*
67  * we can only modify the vlan bindings in physical port
68  * table as we don't own the table, we are not suppose to create
69  * a new port entry in the table, so return from here if entry is
70  * not resolved
71  */
72  return;
73  }
74  table_->Change(this);
75 }
76 
77 void PhysicalPortEntry::Encode(struct ovsdb_idl_txn *txn) {
78  struct ovsdb_wrapper_port_vlan_binding binding[binding_table_.size()];
79  VlanLSTable::iterator it = binding_table_.begin();
80  std::size_t i = 0;
81  for ( ; it != binding_table_.end(); it++) {
82  struct ovsdb_idl_row *ls = it->second->ovs_entry();
83  if (ls != NULL) {
84  binding[i].ls = ls;
85  binding[i].vlan = it->first;
86  i++;
87  }
88  }
90 }
91 
93  binding_table_[vlan] = ls;
94 }
95 
97  binding_table_.erase(vlan);
98 }
99 
100 const std::string &PhysicalPortEntry::name() const {
101  return name_;
102 }
103 
104 const std::string &PhysicalPortEntry::dev_name() const {
105  return dev_name_;
106 }
107 
110  return binding_table_;
111 }
112 
115  return ovs_binding_table_;
116 }
117 
120  return stats_table_;
121 }
122 
124  struct ovsdb_idl_txn *txn =
126  if (txn == NULL) {
127  // failed to create transaction because of idl marked for
128  // deletion return from here.
129  return true;
130  }
131  Encode(txn);
132  struct jsonrpc_msg *msg = ovsdb_wrapper_idl_txn_encode(txn);
133  if (msg == NULL) {
134  table_->client_idl()->DeleteTxn(txn);
135  return true;
136  }
137  OVSDB_TRACE(Trace, "Sending Vlan Port Binding update for Physical route " +
138  dev_name_ + " Physical Port " + name_);
140  return false;
141 }
142 
144  OvsdbObject(idl), stale_create_done_(false) {
146  boost::bind(&PhysicalPortTable::Notify, this, _1, _2));
147 }
148 
150 }
151 
153  struct ovsdb_idl_row *row) {
154  if (op == OvsdbClientIdl::OVSDB_DEL) {
155  DeletePortEntry(row);
156  } else if (op == OvsdbClientIdl::OVSDB_ADD) {
157  PhysicalPortEntry *entry = FindPortEntry(row);
158  if (entry) {
159  EntryOvsdbUpdate(entry);
160  }
161  }
162 }
163 
164 KSyncEntry *PhysicalPortTable::Alloc(const KSyncEntry *key, uint32_t index) {
165  const PhysicalPortEntry *k_entry =
166  static_cast<const PhysicalPortEntry *>(key);
167  PhysicalPortEntry *entry = new PhysicalPortEntry(this, k_entry->dev_name_,
168  k_entry->name_);
169  return entry;
170 }
171 
172 void PhysicalPortTable::CreatePortEntry(struct ovsdb_idl_row *row,
173  const std::string &physical_device) {
174  assert(FindPortEntry(row) == NULL);
175  // Create a port entry and add to the idl entry map
176  PhysicalPortEntry key(this, physical_device,
178  PhysicalPortEntry *entry = static_cast<PhysicalPortEntry *>(Find(&key));
179  if (entry == NULL) {
180  OVSDB_TRACE(Trace, "Add/Change of Physical Port " +
181  std::string(ovsdb_wrapper_physical_port_name(row)));
182  entry = static_cast<PhysicalPortEntry *>(Create(&key));
183  entry->ovs_entry_ = row;
184  } else if (!entry->IsActive()) {
185  // entry is present but it is a temp entry.
186  OVSDB_TRACE(Trace, "Add/Change of Physical Port " +
187  std::string(ovsdb_wrapper_physical_port_name(row)));
188  Change(entry);
189  // Set row pointer after triggering change to activate entry
190  // so that message is not encoded.
191  entry->ovs_entry_ = row;
192  }
193  EntryOvsdbUpdate(entry);
194  idl_entry_map_[row] = entry;
195 }
196 
198  IdlEntryMap::iterator it = idl_entry_map_.find(row);
199  if (it != idl_entry_map_.end()) {
200  return it->second;
201  }
202 
203  return NULL;
204 }
205 
206 void PhysicalPortTable::DeletePortEntry(struct ovsdb_idl_row *row) {
207  PhysicalPortEntry *entry = FindPortEntry(row);
208  if (entry == NULL) {
209  return;
210  }
211 
212  OVSDB_TRACE(Trace, "Delete of Physical Port " +
213  std::string(ovsdb_wrapper_physical_port_name(row)));
214  idl_entry_map_.erase(row);
215  entry->ovs_entry_ = NULL;
216  Delete(entry);
217 }
218 
220  stale_create_done_ = true;
221 }
222 
224  std::size_t count =
226  struct ovsdb_wrapper_port_vlan_binding new_bind[count];
228 
229  // clear the old ovs_binding_table and fill new entries.
230  entry->ovs_binding_table_.clear();
231  for (std::size_t i = 0; i < count; i++) {
232  LogicalSwitchEntry key(client_idl_->logical_switch_table(),
234  LogicalSwitchEntry *ls_entry =
235  static_cast<LogicalSwitchEntry *>(
236  client_idl_->logical_switch_table()->Find(&key));
237  if (ls_entry != NULL) {
238  entry->ovs_binding_table_[new_bind[i].vlan] = ls_entry;
239  }
240  }
241 
242  // Compare difference between tor agent and ovsdb server.
243  // on mis-match override and re-program Physical port
244  PhysicalPortEntry::VlanLSTable::iterator it =
245  entry->binding_table_.begin();
246  PhysicalPortEntry::VlanLSTable::iterator ovs_it =
247  entry->ovs_binding_table_.begin();
248  VlanPortBindingTable *vp_binding_table = client_idl_->vlan_port_table();
249  bool ret_override = false;
250  while (ovs_it != entry->ovs_binding_table_.end()) {
251  if (it != entry->binding_table_.end() && it->first == ovs_it->first) {
252  if (it->second != ovs_it->second) {
253  // mis-match of logical switch for the vlan
254  //break;
255  ret_override = true;
256  }
257  it++;
258  ovs_it++;
259  } else {
260  ret_override = true;
261  // mis-match of vlans in binding
262  if (stale_create_done_) {
263  // done creating stale entries, bail out and override
264  break;
265  }
266  if (it == entry->binding_table_.end() || it->first > ovs_it->first) {
267  // Create stale vlan port binding entry
268  VlanPortBindingEntry key(vp_binding_table, entry->dev_name(),
269  entry->name(), ovs_it->first,
270  ovs_it->second->name());
271  vp_binding_table->CreateStale(&key);
272  ovs_it++;
273  } else {
274  it++;
275  }
276  }
277  }
278 
279  if (entry->binding_table_.size() != entry->ovs_binding_table_.size()) {
280  // we need to anyway override OVSDB if the table size are different
281  ret_override = true;
282  }
283 
285  struct ovsdb_wrapper_port_vlan_stats stats[count];
287  entry->stats_table_.clear();
288  for (std::size_t i = 0; i < count; i++) {
289  entry->stats_table_[stats[i].vlan] = stats[i].stats;
290  }
291 
292  if (ret_override) {
293  // change entry to update vlan port bindings
294  Change(entry);
295  }
296 }
297 
299 // Sandesh routines
302  AgentSandeshArguments &args) :
303  OvsdbSandeshTask(resp_ctx, args), name_("") {
304  if (false == args.Get("name", &name_)) {
305  name_ = "";
306  }
307 }
308 
310  const std::string &ip,
311  uint32_t port,
312  const std::string &name) :
313  OvsdbSandeshTask(resp_ctx, ip, port), name_(name) {
314 }
315 
317 }
318 
320  if (!name_.empty()) {
321  args.Add("name", name_);
322  }
323 }
324 
327  if (!name_.empty()) {
328  PhysicalPortEntry *entry = static_cast<PhysicalPortEntry *>(kentry);
329  if (entry->name().find(name_) != std::string::npos) {
330  return FilterAllow;
331  }
332  return FilterDeny;
333  }
334  return FilterAllow;
335 }
336 
338  SandeshResponse *resp) {
339  PhysicalPortEntry *entry = static_cast<PhysicalPortEntry *>(kentry);
340  OvsdbPhysicalPortEntry pentry;
341  pentry.set_state(entry->StateString());
342  pentry.set_switch_name(entry->dev_name());
343  pentry.set_name(entry->name());
344  const PhysicalPortEntry::VlanLSTable &bindings =
345  entry->binding_table();
346  const PhysicalPortEntry::VlanStatsTable &stats_table =
347  entry->stats_table();
348  PhysicalPortEntry::VlanLSTable::const_iterator it =
349  bindings.begin();
350  std::vector<OvsdbPhysicalPortVlanInfo> vlan_list;
351  for (; it != bindings.end(); it++) {
352  OvsdbPhysicalPortVlanInfo vlan;
353  vlan.set_vlan(it->first);
354  vlan.set_logical_switch(it->second->name());
355  PhysicalPortEntry::VlanStatsTable::const_iterator stats_it =
356  stats_table.find(it->first);
357  if (stats_it != stats_table.end()) {
358  int64_t in_pkts, in_bytes, out_pkts, out_bytes;
360  &in_pkts, &in_bytes, &out_pkts, &out_bytes);
361  vlan.set_in_pkts(in_pkts);
362  vlan.set_in_bytes(in_bytes);
363  vlan.set_out_pkts(out_pkts);
364  vlan.set_out_bytes(out_bytes);
365  } else {
366  vlan.set_in_pkts(0);
367  vlan.set_in_bytes(0);
368  vlan.set_out_pkts(0);
369  vlan.set_out_bytes(0);
370  }
371  vlan_list.push_back(vlan);
372  }
373  pentry.set_vlans(vlan_list);
374 
375  OvsdbPhysicalPortResp *port_resp =
376  static_cast<OvsdbPhysicalPortResp *>(resp);
377  std::vector<OvsdbPhysicalPortEntry> &port_list =
378  const_cast<std::vector<OvsdbPhysicalPortEntry>&>(
379  port_resp->get_port());
380  port_list.push_back(pentry);
381 }
382 
384  return static_cast<SandeshResponse *>(new OvsdbPhysicalPortResp());
385 }
386 
388  return static_cast<KSyncObject *>(
389  session->client_idl()->physical_port_table());
390 }
391 
392 void OvsdbPhysicalPortReq::HandleRequest() const {
394  new PhysicalPortSandeshTask(context(), get_session_remote_ip(),
395  get_session_remote_port(),
396  get_name());
398  scheduler->Enqueue(task);
399 }
400 
void UpdateResp(KSyncEntry *kentry, SandeshResponse *resp)
#define OVSDB_TRACE(obj,...)
void Change(KSyncEntry *entry)
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
const VlanLSTable & binding_table() const
bool IsResolved()
void ovsdb_wrapper_physical_port_vlan_stats(struct ovsdb_idl_row *row, struct ovsdb_wrapper_port_vlan_stats *)
std::string StateString() const
char * ovsdb_wrapper_logical_switch_name(struct ovsdb_idl_row *row)
const std::string & dev_name() const
bool IsLess(const KSyncEntry &) const
void Delete(KSyncEntry *entry)
void EntryOvsdbUpdate(PhysicalPortEntry *entry)
PhysicalPortTable(OvsdbClientIdl *idl)
std::map< uint32_t, struct ovsdb_idl_row * > VlanStatsTable
void ovsdb_wrapper_physical_port_vlan_binding(struct ovsdb_idl_row *row, struct ovsdb_wrapper_port_vlan_binding *)
void Register(EntryType type, NotifyCB cb)
struct ovsdb_idl_row * stats
Definition: ovsdb_wrapper.h:17
void EncodeArgs(AgentSandeshArguments &args)
void DeleteTxn(struct ovsdb_idl_txn *txn)
struct ovsdb_idl_row * ovs_entry_
Definition: ovsdb_entry.h:53
KSyncEntry * Alloc(const KSyncEntry *key, uint32_t index)
void DeletePortEntry(struct ovsdb_idl_row *row)
bool Get(const std::string &key, std::string *val) const
KSyncObject * GetObject(OvsdbClientSession *session)
static TaskScheduler * GetInstance()
Definition: task.cc:547
FilterResp Filter(KSyncEntry *entry)
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 * ls
Definition: ovsdb_wrapper.h:12
void ovsdb_wrapper_get_logical_binding_stats(struct ovsdb_idl_row *row, int64_t *in_pkts, int64_t *in_bytes, int64_t *out_pkts, int64_t *out_bytes)
Definition: trace.h:220
KSyncEntry * Find(const KSyncEntry *key)
Definition: ksync_object.cc:99
void CreatePortEntry(struct ovsdb_idl_row *row, const std::string &physical_device)
struct ovsdb_idl_row * ovs_entry()
Definition: ovsdb_entry.h:47
PhysicalPortSandeshTask(std::string resp_ctx, AgentSandeshArguments &args)
const VlanLSTable & ovs_binding_table() const
bool Add(const std::string &key, const std::string &val)
void Encode(struct ovsdb_idl_txn *)
bool IsActive()
Definition: ksync_entry.h:172
KSyncEntry * Create(const KSyncEntry *key)
size_t ovsdb_wrapper_physical_port_vlan_stats_count(struct ovsdb_idl_row *row)
std::map< uint32_t, LogicalSwitchEntry * > VlanLSTable
void AddBinding(int16_t vlan, LogicalSwitchEntry *ls)
char * ovsdb_wrapper_physical_port_name(struct ovsdb_idl_row *row)
KSyncEntry * CreateStale(const KSyncEntry *key)
PhysicalPortTable * physical_port_table()
void DeleteBinding(int16_t vlan, LogicalSwitchEntry *ls)
struct jsonrpc_msg * ovsdb_wrapper_idl_txn_encode(struct ovsdb_idl_txn *txn)
OvsdbObject * table_
Definition: ovsdb_entry.h:52
PhysicalPortEntry(PhysicalPortTable *table, const std::string &dev_name, const std::string &name)
void Notify(OvsdbClientIdl::Op, struct ovsdb_idl_row *)
void ovsdb_wrapper_update_physical_port(struct ovsdb_idl_txn *, struct ovsdb_idl_row *, struct ovsdb_wrapper_port_vlan_binding *, size_t binding_count)
size_t ovsdb_wrapper_physical_port_vlan_binding_count(struct ovsdb_idl_row *row)
void TxnScheduleJsonRpc(struct jsonrpc_msg *msg)
const std::string & name() const
const VlanStatsTable & stats_table() const
PhysicalPortEntry * FindPortEntry(struct ovsdb_idl_row *row)
OvsdbClientIdlPtr client_idl_
Definition: ovsdb_object.h:34
struct ovsdb_idl_txn * CreateTxn(OvsdbEntryBase *entry, KSyncEntry::KSyncEvent ack_event=KSyncEntry::ADD_ACK)
struct task_ task
OvsdbClientIdl * client_idl()
Definition: ovsdb_object.h:31