OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
physical_switch_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>
16 #include <physical_switch_ovsdb.h>
17 #include <logical_switch_ovsdb.h>
18 #include <physical_port_ovsdb.h>
19 #include <ovsdb_types.h>
20 
21 using OVSDB::OvsdbClient;
25 
26 PhysicalSwitchEntry::PhysicalSwitchEntry(PhysicalSwitchTable *table,
27  const std::string &name) : OvsdbEntry(table), name_(name),
28  tunnel_ip_() {
29 }
30 
32 }
33 
36  name_, table_->client_idl());
37  return true;
38 }
39 
42  name_, table_->client_idl());
43  return true;
44 }
45 
47  return tunnel_ip_;
48 }
49 
50 const std::string &PhysicalSwitchEntry::name() {
51  return name_;
52 }
53 
54 void PhysicalSwitchEntry::set_tunnel_ip(std::string ip) {
55  boost::system::error_code ec;
56  tunnel_ip_ = Ip4Address::from_string(ip, ec);
57 }
58 
59 bool PhysicalSwitchEntry::IsLess(const KSyncEntry &entry) const {
60  const PhysicalSwitchEntry &ps_entry =
61  static_cast<const PhysicalSwitchEntry&>(entry);
62  return (name_ < ps_entry.name_);
63 }
64 
66  return NULL;
67 }
68 
70  SandeshPhysicalSwitchInfo info;
71  if (event == ADD) {
72  info.set_op("Add");
73  } else {
74  info.set_op("Delete");
75  }
76  info.set_name(name_);
77  OVSDB_TRACE(PhysicalSwitch, info);
78 }
79 
81  OvsdbObject(idl), update_ports_(false) {
83  boost::bind(&PhysicalSwitchTable::Notify, this, _1, _2));
84 }
85 
87 }
88 
90  struct ovsdb_idl_row *row) {
91  PhysicalSwitchEntry *row_entry = FindSwitchEntry(row);
92  if (op == OvsdbClientIdl::OVSDB_DEL) {
93  TriggerDelete(row_entry);
94  } else if (op == OvsdbClientIdl::OVSDB_ADD) {
95  std::string ps_name(ovsdb_wrapper_physical_switch_name(row));
96  PhysicalSwitchEntry key(this, ps_name);
97  PhysicalSwitchEntry *entry =
98  static_cast<PhysicalSwitchEntry *>(FindActiveEntry(&key));
99  if (entry != row_entry) {
100  // Physical Switch name has been changed trigger delete
101  // for both the entries to cleanup and re-add the newly
102  // created entry
103  TriggerDelete(row_entry);
104  TriggerDelete(entry);
105  row_entry = NULL;
106  entry = NULL;
107  }
108  if (entry == NULL) {
109  entry = static_cast<PhysicalSwitchEntry *>(Create(&key));
111  entry->ovs_entry_ = row;
112  idl_entry_map_[row] = entry;
113  }
115 
116  // check if we need to skip ports updation
117  if (update_ports_) {
118  UpdatePorts(entry);
119  }
120  } else {
121  assert(0);
122  }
123 }
124 
125 KSyncEntry *PhysicalSwitchTable::Alloc(const KSyncEntry *key, uint32_t index) {
126  const PhysicalSwitchEntry *k_entry =
127  static_cast<const PhysicalSwitchEntry *>(key);
128  PhysicalSwitchEntry *entry = new PhysicalSwitchEntry(this, k_entry->name_);
129  return entry;
130 }
131 
133  if (update_ports_) {
134  return;
135  }
136  update_ports_ = true;
137  PhysicalSwitchEntry *entry = static_cast<PhysicalSwitchEntry *>(Next(NULL));
138  while (entry != NULL) {
139  // Trigger Update Ports to update pending physical port entries
140  UpdatePorts(entry);
141  entry = static_cast<PhysicalSwitchEntry *>(Next(entry));
142  }
143 }
144 
146  if (entry == NULL) {
147  return;
148  }
150  idl_entry_map_.erase(entry->ovs_entry_);
151  entry->ovs_entry_ = NULL;
152  // UpdatePorts after reseting ovs_entry_ to NULL will result in
153  // clean up of all the ports
154  UpdatePorts(entry);
155  Delete(entry);
156 }
157 
161  entry->intf_list_.clear();
162  if (entry->ovs_entry_ != NULL) {
163  std::size_t count =
165  struct ovsdb_idl_row *ports[count];
166  ovsdb_wrapper_physical_switch_ports(entry->ovs_entry_, ports, count);
167  std::size_t i = 0;
168  while (i < count) {
169  entry->intf_list_.insert(ports[i]);
170  if (old.erase(ports[i]) == 0) {
171  // if entry was not present eariler trigger Add.
172  p_table->CreatePortEntry(ports[i], entry->name());
173  }
174  i++;
175  }
176  }
177  PhysicalSwitchEntry::InterfaceList::iterator it = old.begin();
178  while (it != old.end()) {
179  // trigger del notify for ovs idl row
180  p_table->DeletePortEntry(*it);
181  old.erase(it);
182  it = old.begin();
183  }
184 }
185 
187  struct ovsdb_idl_row *row) {
188  IdlEntryMap::iterator it = idl_entry_map_.find(row);
189  if (it != idl_entry_map_.end()) {
190  return it->second;
191  }
192 
193  return NULL;
194 }
195 
197 // Sandesh routines
200 public:
201  PhysicalSwitchSandeshTask(std::string resp_ctx, const std::string &ip,
202  uint32_t port) :
203  Task((TaskScheduler::GetInstance()->GetTaskId("Agent::KSync")), 0),
204  resp_(new OvsdbPhysicalSwitchResp()), resp_data_(resp_ctx),
205  ip_(ip), port_(port) {
206  }
208  virtual bool Run() {
209  std::vector<OvsdbPhysicalSwitchEntry> pswitch;
210  OvsdbClientSession *session;
211  if (ip_.empty()) {
212  session = Agent::GetInstance()->ovsdb_client()->NextSession(NULL);
213  } else {
214  boost::system::error_code ec;
215  Ip4Address ip_addr = Ip4Address::from_string(ip_, ec);
216  session = Agent::GetInstance()->ovsdb_client()->FindSession(ip_addr,
217  port_);
218  }
219  if (session != NULL && session->client_idl() != NULL) {
220  PhysicalSwitchTable *table =
221  session->client_idl()->physical_switch_table();
222  PhysicalSwitchEntry *entry =
223  static_cast<PhysicalSwitchEntry *>(table->Next(NULL));
224  while (entry != NULL) {
225  OvsdbPhysicalSwitchEntry pentry;
226  pentry.set_state(entry->StateString());
227  pentry.set_name(entry->name());
228  pentry.set_tunnel_ip(entry->tunnel_ip().to_string());
229  pswitch.push_back(pentry);
230  entry = static_cast<PhysicalSwitchEntry *>(table->Next(entry));
231  }
232  }
233  resp_->set_pswitch(pswitch);
234  SendResponse();
235  return true;
236  }
237  std::string Description() const { return "PhysicalSwitchSandeshTask"; }
238 private:
239  void SendResponse() {
240  resp_->set_context(resp_data_);
241  resp_->set_more(false);
242  resp_->Response();
243  }
244 
245  OvsdbPhysicalSwitchResp *resp_;
246  std::string resp_data_;
247  std::string ip_;
248  uint32_t port_;
250 };
251 
252 void OvsdbPhysicalSwitchReq::HandleRequest() const {
254  new PhysicalSwitchSandeshTask(context(), get_session_remote_ip(),
255  get_session_remote_port());
257  scheduler->Enqueue(task);
258 }
259 
OVSDB::OvsdbClient * ovsdb_client() const
Definition: agent.h:1126
#define OVSDB_TRACE(obj,...)
void AddIdlToConnectionState(const std::string &device_name, OvsdbClientIdl *idl)
static Agent * GetInstance()
Definition: agent.h:436
KSyncEntry * Next(const KSyncEntry *entry) const
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
bool IsLess(const KSyncEntry &) const
char * ovsdb_wrapper_physical_switch_name(struct ovsdb_idl_row *row)
void SendResponse(HttpSession *session, const std::string &msg, int status_code)
std::set< struct ovsdb_idl_row * > InterfaceList
PhysicalSwitchTable(OvsdbClientIdl *idl)
virtual bool Run()
Code to execute. Returns true if task is completed. Return false to reschedule the task...
OvsdbPhysicalSwitchResp * resp_
std::string StateString() const
void TriggerDelete(PhysicalSwitchEntry *entry)
void Delete(KSyncEntry *entry)
ConnectionStateTable * connection_table()
Definition: task_int.h:10
void DelIdlToConnectionState(const std::string &device_name, OvsdbClientIdl *idl)
void Register(EntryType type, NotifyCB cb)
KSyncEntry * FindActiveEntry(KSyncEntry *key)
Definition: ovsdb_object.cc:23
struct ovsdb_idl_row * ovs_entry_
Definition: ovsdb_entry.h:53
void DeletePortEntry(struct ovsdb_idl_row *row)
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
PhysicalSwitchEntry * FindSwitchEntry(struct ovsdb_idl_row *row)
void ovsdb_wrapper_physical_switch_ports(struct ovsdb_idl_row *row, struct ovsdb_idl_row **ports, size_t n)
Definition: trace.h:220
std::string Description() const
#define DISALLOW_COPY_AND_ASSIGN(_Class)
Definition: util.h:15
void UpdatePorts(PhysicalSwitchEntry *entry)
void CreatePortEntry(struct ovsdb_idl_row *row, const std::string &physical_device)
virtual OvsdbClientSession * FindSession(Ip4Address ip, uint16_t port)=0
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
KSyncEntry * Create(const KSyncEntry *key)
void Notify(OvsdbClientIdl::Op, struct ovsdb_idl_row *)
PhysicalPortTable * physical_port_table()
OvsdbObject * table_
Definition: ovsdb_entry.h:52
size_t ovsdb_wrapper_physical_switch_ports_count(struct ovsdb_idl_row *row)
void SendTrace(Trace event) const
PhysicalSwitchSandeshTask(std::string resp_ctx, const std::string &ip, uint32_t port)
KSyncEntry * Alloc(const KSyncEntry *key, uint32_t index)
void set_tunnel_ip(std::string ip)
Task is a wrapper over tbb::task to support policies.
Definition: task.h:86
virtual OvsdbClientSession * NextSession(OvsdbClientSession *session)=0
const char * ovsdb_wrapper_physical_switch_tunnel_ip(struct ovsdb_idl_row *row)
OvsdbClientIdl * client_idl()
Definition: ovsdb_object.h:31
PhysicalSwitchTable * physical_switch_table()