OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
vlan_port_binding_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 };
9 #include <ovsdb_client.h>
10 #include <ovsdb_client_idl.h>
11 #include <ovsdb_client_session.h>
12 #include <physical_switch_ovsdb.h>
13 #include <logical_switch_ovsdb.h>
14 #include <physical_port_ovsdb.h>
16 #include <vm_interface_ksync.h>
17 
18 #include <oper/vn.h>
19 #include <oper/interface_common.h>
21 #include <ovsdb_sandesh.h>
22 #include <ovsdb_types.h>
23 
24 using namespace OVSDB;
25 
27  const std::string &physical_device, const std::string &physical_port,
28  uint16_t vlan_tag, const std::string &logical_switch) :
29  OvsdbDBEntry(table), logical_switch_name_(logical_switch),
30  physical_port_name_(physical_port), physical_device_name_(physical_device),
31  vlan_(vlan_tag), vmi_uuid_(boost::uuids::nil_uuid()),
32  old_logical_switch_name_(), logical_switch_(NULL, this) {
33 }
34 
36  const VlanLogicalInterface *entry) : OvsdbDBEntry(table),
37  logical_switch_name_(), physical_port_name_(entry->phy_intf_display_name()),
38  physical_device_name_(entry->phy_dev_display_name()), vlan_(entry->vlan()),
39  vmi_uuid_(boost::uuids::nil_uuid()), old_logical_switch_name_(),
40  logical_switch_(NULL, this) {
41 }
42 
44  const VlanPortBindingEntry *key) : OvsdbDBEntry(table),
45  logical_switch_name_(key->logical_switch_name_),
46  physical_port_name_(key->physical_port_name_),
47  physical_device_name_(key->physical_device_name_), vlan_(key->vlan_),
48  vmi_uuid_(boost::uuids::nil_uuid()), old_logical_switch_name_(),
49  logical_switch_(NULL, this) {
50 }
51 
53  if (!logical_switch_name_.empty()) {
54  LogicalSwitchTable *l_table =
56  LogicalSwitchEntry ls_key(l_table, logical_switch_name_.c_str());
58  static_cast<LogicalSwitchEntry *>(l_table->GetReference(&ls_key));
59  } else {
60  logical_switch_ = NULL;
61  }
62 }
63 
65  logical_switch_ = NULL;
66 }
67 
68 void VlanPortBindingEntry::AddMsg(struct ovsdb_idl_txn *txn) {
71  physical_port_ = p_table->GetReference(&key);
72  PhysicalPortEntry *port =
73  static_cast<PhysicalPortEntry *>(physical_port_.get());
74 
75  // update logical switch name propagated to OVSDB server, this will
76  // be used in change Operation to reduce the unncessary computation
77  // when there is change which VlanPortBindingEntry is not
78  // interested into
80  if (!logical_switch_name_.empty()) {
81  port->AddBinding(vlan_,
82  static_cast<LogicalSwitchEntry *>(logical_switch_.get()));
83  OVSDB_TRACE(Trace, "Adding port vlan binding port " +
85  " to Logical Switch " + logical_switch_name_);
86  } else {
87  OVSDB_TRACE(Trace, "Deleting port vlan binding port " +
89  port->DeleteBinding(vlan_, NULL);
90  }
91 
92  // Don't trigger update for stale entries
93  if (!stale()) {
94  port->TriggerUpdate();
95  }
96 }
97 
98 void VlanPortBindingEntry::ChangeMsg(struct ovsdb_idl_txn *txn) {
100  // no change return from here.
101  return;
102  }
103  PhysicalPortEntry *port =
104  static_cast<PhysicalPortEntry *>(physical_port_.get());
105  OVSDB_TRACE(Trace, "Changing port vlan binding port " +
107  port->DeleteBinding(vlan_, NULL);
108 
109  AddMsg(txn);
110 }
111 
112 void VlanPortBindingEntry::DeleteMsg(struct ovsdb_idl_txn *txn) {
113  if (!physical_port_) {
114  return;
115  }
116  PhysicalPortEntry *port =
117  static_cast<PhysicalPortEntry *>(physical_port_.get());
118  OVSDB_TRACE(Trace, "Deleting port vlan binding port " +
120  port->DeleteBinding(vlan_,
121  static_cast<LogicalSwitchEntry *>(logical_switch_.get()));
122  port->TriggerUpdate();
123 }
124 
126  VlanLogicalInterface *entry =
127  static_cast<VlanLogicalInterface *>(db_entry);
128  std::string ls_name =
129  (dynamic_cast<const VlanPortBindingTable *>(table_))->
130  GetLogicalSwitchName(entry);
131  boost::uuids::uuid vmi_uuid(boost::uuids::nil_uuid());
132  bool change = false;
133 
134  if (entry->vm_interface()) {
135  vmi_uuid = entry->vm_interface()->GetUuid();
136  }
137 
138  if (vmi_uuid_ != vmi_uuid) {
139  vmi_uuid_ = vmi_uuid;
140  change = true;
141  }
142 
143  if (ls_name != logical_switch_name_) {
144  logical_switch_name_ = ls_name;
145  change = true;
146  }
147  return change;
148 }
149 
150 bool VlanPortBindingEntry::IsLess(const KSyncEntry &entry) const {
151  const VlanPortBindingEntry &vps_entry =
152  static_cast<const VlanPortBindingEntry&>(entry);
153  if (vlan_ != vps_entry.vlan_)
154  return vlan_ < vps_entry.vlan_;
156  return physical_device_name_ < vps_entry.physical_device_name_;
157  return physical_port_name_ < vps_entry.physical_port_name_;
158 }
159 
161  PhysicalSwitchTable *ps_table =
163  PhysicalSwitchEntry ps_key(ps_table, physical_device_name_.c_str());
164  PhysicalSwitchEntry *p_switch =
165  static_cast<PhysicalSwitchEntry *>(ps_table->GetReference(&ps_key));
166  if (!p_switch->IsResolved()) {
167  OVSDB_TRACE(Trace, "Physical Switch unavailable for Port Vlan Binding "+
169  " to Logical Switch " + logical_switch_name_);
170  return p_switch;
171  }
172 
175  PhysicalPortEntry *p_port =
176  static_cast<PhysicalPortEntry *>(p_table->GetReference(&key));
177  if (!p_port->IsResolved()) {
178  OVSDB_TRACE(Trace, "Physical Port unavailable for Port Vlan Binding " +
180  " to Logical Switch " + logical_switch_name_);
181  return p_port;
182  }
183 
184  // check for VMI only if entry is not stale marked.
185  if (!stale()) {
186  VMInterfaceKSyncObject *vm_intf_table =
188  VMInterfaceKSyncEntry vm_intf_key(vm_intf_table, vmi_uuid_);
189  VMInterfaceKSyncEntry *vm_intf = static_cast<VMInterfaceKSyncEntry *>(
190  vm_intf_table->GetReference(&vm_intf_key));
191  if (!vm_intf->IsResolved()) {
192  OVSDB_TRACE(Trace, "VM Interface unavailable for Port Vlan Binding " +
194  " to Logical Switch " + logical_switch_name_);
195  return vm_intf;
196  } else if (logical_switch_name_.empty()) {
197  // update latest name after resolution.
198  logical_switch_name_ = vm_intf->vn_name();
199  }
200  }
201 
202  if (!logical_switch_name_.empty()) {
203  // Check only if logical switch name is present.
204  LogicalSwitchTable *l_table =
206  LogicalSwitchEntry ls_key(l_table, logical_switch_name_.c_str());
207  LogicalSwitchEntry *ls_entry =
208  static_cast<LogicalSwitchEntry *>(l_table->GetReference(&ls_key));
209  if (!ls_entry->IsResolved()) {
210  OVSDB_TRACE(Trace, "Logical Switch unavailable for Port Vlan "
211  "Binding " + physical_port_name_ + " vlan " +
212  integerToString(vlan_) + " to Logical Switch " +
214  return ls_entry;
215  }
216  }
217 
218  return NULL;
219 }
220 
221 const std::string &VlanPortBindingEntry::logical_switch_name() const {
222  return logical_switch_name_;
223 }
224 
225 const std::string &VlanPortBindingEntry::physical_port_name() const {
226  return physical_port_name_;
227 }
228 
229 const std::string &VlanPortBindingEntry::physical_device_name() const {
230  return physical_device_name_;
231 }
232 
233 uint16_t VlanPortBindingEntry::vlan() const {
234  return vlan_;
235 }
236 
238  OvsdbDBObject(idl, true) {
239 }
240 
242 }
243 
244 KSyncEntry *VlanPortBindingTable::Alloc(const KSyncEntry *key, uint32_t index) {
245  const VlanPortBindingEntry *k_entry =
246  static_cast<const VlanPortBindingEntry *>(key);
247  VlanPortBindingEntry *entry = new VlanPortBindingEntry(this, k_entry);
248  return entry;
249 }
250 
252  const VlanLogicalInterface *entry =
253  static_cast<const VlanLogicalInterface *>(db_entry);
254  VlanPortBindingEntry *key = new VlanPortBindingEntry(this, entry);
255  return static_cast<KSyncEntry *>(key);
256 }
257 
258 std::string
260  const VlanLogicalInterface *entry =
261  dynamic_cast<const VlanLogicalInterface *>(e);
262  std::string ls_name;
263  if (entry->vm_interface() && entry->vm_interface()->vn()) {
264  ls_name = UuidToString(entry->vm_interface()->vn()->GetUuid());
265  }
266 
267  return ls_name;
268 }
269 
271  const DBEntry *entry, const OvsdbDBEntry *ovsdb_entry) {
272  const VlanLogicalInterface *l_port =
273  dynamic_cast<const VlanLogicalInterface *>(entry);
274  if (l_port == NULL) {
275  // Ignore entries other than VLanLogicalInterface.
276  return DBFilterIgnore;
277  }
278 
279  // Logical interface without vm interface is incomplete entry
280  // for ovsdb, trigger delete.
281  if (l_port->vm_interface() == NULL) {
282  if (ovsdb_entry != NULL) {
283  OVSDB_TRACE(Trace, "VM Interface Unavialable, Deleting Logical "
284  "Port " + l_port->name());
285  } else {
286  OVSDB_TRACE(Trace, "VM Interface Unavialable, Ignoring Logical "
287  "Port " + l_port->name());
288  }
289  return DBFilterDelete;
290  }
291 
292  // Since we need physical port name and device name as key, ignore entry
293  // if physical port or device is not yet present.
294  if (l_port->phy_intf_display_name().empty()) {
295  OVSDB_TRACE(Trace, "Ignoring Port Vlan Binding due to physical port "
296  "name unavailablity Logical port = " + l_port->name());
297  return DBFilterIgnore;
298  }
299 
300  if (l_port->phy_dev_display_name().empty()) {
301  OVSDB_TRACE(Trace, "Ignoring Port Vlan Binding due to device name "
302  "unavailablity Logical port = " + l_port->name());
303  return DBFilterIgnore;
304  }
305 
306  // On LS change old vlan-port binding to old LS has to be removed from tor
307  // and new LS need to be added for the same vlan-port
308  if (ovsdb_entry &&
309  (dynamic_cast<const VlanPortBindingEntry*>(ovsdb_entry))->
310  logical_switch_name() != GetLogicalSwitchName(entry)) {
311  return DBFilterDelAdd;
312  }
313 
314  return DBFilterAccept;
315 }
316 
318 // Sandesh routines
321  std::string resp_ctx, AgentSandeshArguments &args) :
322  OvsdbSandeshTask(resp_ctx, args), physical_port_("") {
323  if (false == args.Get("physical_port", &physical_port_)) {
324  physical_port_ = "";
325  }
326 }
327 
329  std::string resp_ctx, const std::string &ip, uint32_t port,
330  const std::string &physical_port) :
331  OvsdbSandeshTask(resp_ctx, ip, port), physical_port_(physical_port) {
332 }
333 
335 }
336 
338  if (!physical_port_.empty()) {
339  args.Add("physical_port", physical_port_);
340  }
341 }
342 
345  if (!physical_port_.empty()) {
346  VlanPortBindingEntry *entry =
347  static_cast<VlanPortBindingEntry *>(kentry);
348  if (entry->physical_port_name().find(
349  physical_port_) != std::string::npos) {
350  return FilterAllow;
351  }
352  return FilterDeny;
353  }
354  return FilterAllow;
355 }
356 
358  SandeshResponse *resp) {
359  VlanPortBindingEntry *entry = static_cast<VlanPortBindingEntry *>(kentry);
360  OvsdbVlanPortBindingEntry oentry;
361  oentry.set_state(entry->StateString());
362  oentry.set_physical_port(entry->physical_port_name());
363  oentry.set_physical_device(entry->physical_device_name());
364  oentry.set_logical_switch(entry->logical_switch_name());
365  oentry.set_vlan(entry->vlan());
366  OvsdbVlanPortBindingResp *v_resp =
367  static_cast<OvsdbVlanPortBindingResp *>(resp);
368  std::vector<OvsdbVlanPortBindingEntry> &bindings =
369  const_cast<std::vector<OvsdbVlanPortBindingEntry>&>(
370  v_resp->get_bindings());
371  bindings.push_back(oentry);
372 }
373 
375  return static_cast<SandeshResponse *>(new OvsdbVlanPortBindingResp());
376 }
377 
378 KSyncObject *
380  return static_cast<KSyncObject *>(
381  session->client_idl()->vlan_port_table());
382 }
383 
384 void OvsdbVlanPortBindingReq::HandleRequest() const {
386  new VlanPortBindingSandeshTask(context(), get_session_remote_ip(),
387  get_session_remote_port(),
388  get_physical_port());
390  scheduler->Enqueue(task);
391 }
#define OVSDB_TRACE(obj,...)
OvsdbClientIdl * client_idl()
Definition: ovsdb_object.h:76
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
const std::string & logical_switch_name() const
bool IsResolved()
VlanPortBindingTable(OvsdbClientIdl *idl)
const boost::uuids::uuid & GetUuid() const
Definition: interface.h:113
void AddMsg(struct ovsdb_idl_txn *)
std::string StateString() const
DBFilterResp OvsdbDBEntryFilter(const DBEntry *entry, const OvsdbDBEntry *ovsdb_entry)
boost::uuids::uuid uuid
static std::string UuidToString(const boost::uuids::uuid &id)
Definition: string_util.h:138
VMInterfaceKSyncObject * vm_interface_table()
const std::string & vn_name() const
KSyncEntry * Alloc(const KSyncEntry *key, uint32_t index)
std::string GetLogicalSwitchName(const DBEntry *entry) const
VlanPortBindingSandeshTask(std::string resp_ctx, AgentSandeshArguments &args)
const std::string & physical_port_name() const
static const std::string integerToString(const NumberType &num)
Definition: string_util.h:19
bool Get(const std::string &key, std::string *val) const
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
Definition: trace.h:220
bool stale() const
Definition: ksync_entry.h:161
const VnEntry * vn() const
FilterResp Filter(KSyncEntry *entry)
bool Add(const std::string &key, const std::string &val)
void UpdateResp(KSyncEntry *kentry, SandeshResponse *resp)
VlanPortBindingEntry(VlanPortBindingTable *table, const std::string &physical_device, const std::string &physical_port, uint16_t vlan_tag, const std::string &logical_switch)
KSyncEntry * GetReference(const KSyncEntry *key)
LogicalSwitchTable * logical_switch_table()
void AddBinding(int16_t vlan, LogicalSwitchEntry *ls)
const std::string & phy_intf_display_name() const
void DeleteMsg(struct ovsdb_idl_txn *)
PhysicalPortTable * physical_port_table()
const std::string & phy_dev_display_name() const
void DeleteBinding(int16_t vlan, LogicalSwitchEntry *ls)
VmInterface * vm_interface() const
KSyncObject * GetObject(OvsdbClientSession *session)
void ChangeMsg(struct ovsdb_idl_txn *)
VlanPortBindingTable * vlan_port_table()
KSyncEntry * DBToKSyncEntry(const DBEntry *)
const std::string & name() const
Definition: interface.h:114
bool IsLess(const KSyncEntry &) const
const boost::uuids::uuid & GetUuid() const
Definition: vn.h:161
void EncodeArgs(AgentSandeshArguments &args)
const std::string & physical_device_name() const
OvsdbDBObject * table_
Definition: ovsdb_entry.h:110
struct task_ task
PhysicalSwitchTable * physical_switch_table()