OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ovsdb_sandesh.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
3  */
4 
6 
7 #include <ovsdb_client.h>
8 #include <ovsdb_client_idl.h>
9 #include <ovsdb_client_session.h>
10 #include <ovsdb_object.h>
11 #include <ovsdb_sandesh.h>
12 #include <ovsdb_types.h>
13 
14 using namespace OVSDB;
15 
16 static void SandeshError(const std::string msg, const std::string &context) {
17  ErrorResp *resp = new ErrorResp();
18  resp->set_resp(msg);
19  resp->set_context(context);
20  resp->Response();
21 }
22 
23 static void SetErrorMsg(bool &error, std::string &error_msg, std::string msg) {
24  if (error) {
25  // previous error present, add separator
26  error_msg += ", ";
27  }
28  error_msg += msg;
29  error = true;
30 }
31 
33  AgentSandeshArguments &args) :
34  Task((TaskScheduler::GetInstance()->GetTaskId("Agent::KSync")), 0),
35  ip_(), port_(0), resp_(NULL), resp_data_(resp_ctx), first_(0),
36  last_(kEntriesPerPage - 1), total_count_(0), needs_next_(false),
37  error_(false), error_msg_("") {
38  if (!args.Get("session_ip", &ip_)) {
39  SetErrorMsg(error_, error_msg_, "Error fetching session ip");
40  }
41 
42  int val;
43  if (args.Get("session_port", &val)) {
44  port_ = (uint32_t) val;
45  } else {
46  SetErrorMsg(error_, error_msg_, "Error fetching session port");
47  }
48 
49  if (args.Get("first", &val)) {
50  first_ = (uint32_t) val;
51  } else {
52  SetErrorMsg(error_, error_msg_, "Error fetching first");
53  }
54 
55  if (args.Get("last", &val)) {
56  last_ = (uint32_t) val;
57  } else {
58  SetErrorMsg(error_, error_msg_, "Error fetching last");
59  }
60 }
61 
62 OvsdbSandeshTask::OvsdbSandeshTask(std::string resp_ctx, const std::string &ip,
63  uint32_t port) :
64  Task((TaskScheduler::GetInstance()->GetTaskId("Agent::KSync")), 0),
65  ip_(ip), port_(port), resp_(NULL), resp_data_(resp_ctx), first_(0),
66  last_(kEntriesPerPage - 1), total_count_(0), needs_next_(false),
67  error_(false), error_msg_("") {
68 }
69 
71 }
72 
74  if (error_) {
76  return true;
77  }
78  OvsdbClient *ovsdb_client = Agent::GetInstance()->ovsdb_client();
79  OvsdbClientSession *session;
80  if (ip_.empty()) {
81  session = ovsdb_client->NextSession(NULL);
82  } else {
83  boost::system::error_code ec;
84  Ip4Address ip_addr = Ip4Address::from_string(ip_, ec);
85  session = ovsdb_client->FindSession(ip_addr, port_);
86  }
87  uint32_t table_size = 0;
88  uint32_t display_count = 0;
89  if (NoSessionObject() == true ||
90  (session != NULL && session->client_idl() != NULL)) {
91  KSyncObject *table = NULL;
92  if (NoSessionObject()) {
93  table = GetObject(NULL);
94  } else {
95  ip_ = session->remote_ip().to_string();
96  port_ = session->remote_port();
97  table = GetObject(session);
98  }
99 
100  if (table == NULL) {
101  SandeshError("Error: Ovsdb Object not available", resp_data_);
102  return true;
103  }
104 
105  KSyncEntry *entry = table->Next(NULL);
106  table_size = table->Size();
107  uint8_t cur_count = 0;
108  while (entry != NULL) {
109  if (FilterAllow == Filter(entry)) {
110  if ((first_ == (uint32_t)-1 || total_count_ >= first_) &&
111  (total_count_ <= last_)) {
112  cur_count++;
113  display_count++;
114  // allocate resp if not available
115  if (resp_ == NULL)
116  resp_ = Alloc();
117  UpdateResp(entry, resp_);
118  }
119  total_count_++;
120  }
121  entry = table->Next(entry);
122  if (total_count_ == (last_ + 1)) {
123  if (entry != NULL) {
124  // will need next page link
125  needs_next_ = true;
126  }
127  }
128  if (cur_count == kEntriesPerSandesh && entry != NULL) {
129  SendResponse(true);
130  cur_count = 0;
131  }
132  }
133  } else {
134  SandeshError("Error: Session not available", resp_data_);
135  return true;
136  }
137 
138  SendResponse(true);
139 
140  EncodeSendPageReq(display_count, table_size);
141  return true;
142 }
143 
146  std::string s;
147  args.Add("ovsdb_table", GetTableType());
148  args.Add("session_ip", ip_);
149  args.Add("session_port", port_);
150  EncodeArgs(args);
151  args.Add("first", 0);
152  args.Add("last", kEntriesPerPage - 1);
153  args.Encode(&s);
154 
155  return s;
156 }
157 
158 void OvsdbSandeshTask::EncodeSendPageReq(uint32_t display_count,
159  uint32_t table_size) {
160  OvsdbPageResp *resp = new OvsdbPageResp();
162  OvsdbPageRespData resp_data;
163  std::string s;
164  args.Add("ovsdb_table", GetTableType());
165  args.Add("session_ip", ip_);
166  args.Add("session_port", port_);
167  EncodeArgs(args);
168 
169  // encode first page
170  args.Add("first", 0);
171  args.Add("last", kEntriesPerPage - 1);
172  args.Encode(&s);
173  args.Del("first");
174  args.Del("last");
175  resp_data.set_first_page(s);
176  s.clear();
177 
178  uint32_t first = 0;
179  // encode prev page
180  if (first_ != 0 && first_ != (uint32_t)-1 && first_ <= total_count_) {
181  first = first_;
182  args.Add("first",
184  args.Add("last",
185  (first_ < kEntriesPerPage) ? (kEntriesPerPage -1) : (first_ - 1));
186  args.Encode(&s);
187  args.Del("first");
188  args.Del("last");
189  resp_data.set_prev_page(s);
190  s.clear();
191  }
192 
193  // encode next page
194  if (needs_next_) {
195  args.Add("first", last_ + 1);
196  args.Add("last", last_ + kEntriesPerPage);
197  args.Encode(&s);
198  args.Del("first");
199  args.Del("last");
200  resp_data.set_next_page(s);
201  s.clear();
202  }
203 
204  // encode all page
205  args.Add("first", -1);
206  args.Add("last", -1);
207  args.Encode(&s);
208  args.Del("first");
209  args.Del("last");
210  resp_data.set_all(s);
211  s.clear();
212 
213  std::stringstream match_str;
214  if (display_count != 0) {
215  uint32_t last = first + display_count - 1;
216  match_str << first << " - " << (last);
217  } else {
218  match_str << "0";
219  }
220  match_str << " / " << total_count_;
221  resp_data.set_entries(match_str.str());
222  resp_data.set_table_size(table_size);
223 
224  resp->set_req(resp_data);
225  resp_ = resp;
226  SendResponse(false);
227 }
228 
230  if (resp_ == NULL) {
231  // no response formed to send
232  return;
233  }
235  resp_->set_more(more);
236  resp_->Response();
237  resp_ = NULL;
238 }
239 
240 void OvsdbPageReq::HandleRequest() const {
242  args.Decode(get_key());
243 
244  OvsdbSandeshTask *task = NULL;
245  int table_type;
246  args.Get("ovsdb_table", &table_type);
247  switch (table_type) {
249  task = new PhysicalPortSandeshTask(context(), args);
250  break;
252  task = new LogicalSwitchSandeshTask(context(), args);
253  break;
255  task = new VlanPortBindingSandeshTask(context(), args);
256  break;
258  task = new OvsdbVrfSandeshTask(context(), args);
259  break;
261  task = new UnicastMacRemoteSandeshTask(context(), args);
262  break;
264  task = new UnicastMacLocalSandeshTask(context(), args);
265  break;
267  task = new MulticastMacLocalSandeshTask(context(), args);
268  break;
270  task = new HaStaleDevVnSandeshTask(context(), args);
271  break;
273  task = new HaStaleL2RouteSandeshTask(context(), args);
274  break;
275  default:
276  break;
277  }
278 
279  if (task != NULL) {
281  scheduler->Enqueue(task);
282  } else {
283  SandeshError("Error: Invalid table type", context());
284  }
285 }
286 
OVSDB::OvsdbClient * ovsdb_client() const
Definition: agent.h:1126
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
int Encode(std::string *str)
OvsdbSandeshTask(std::string resp_ctx, AgentSandeshArguments &args)
SandeshResponse * resp_
Definition: ovsdb_sandesh.h:64
virtual uint16_t remote_port() const =0
void EncodeSendPageReq(uint32_t display_count, uint32_t table_size)
virtual Ip4Address remote_ip() const =0
std::string EncodeFirstPage()
bool Del(const std::string &key)
virtual void Response()
Definition: p/sandesh.h:502
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
static void SetErrorMsg(bool &error, std::string &error_msg, std::string msg)
bool Run()
Code to execute. Returns true if task is completed. Return false to reschedule the task...
virtual TableType GetTableType()=0
std::size_t Size()
Definition: ksync_object.h:144
void SendResponse(bool more)
bool Add(const std::string &key, const std::string &val)
virtual bool NoSessionObject()
Definition: ovsdb_sandesh.h:58
virtual OvsdbClientSession * FindSession(Ip4Address ip, uint16_t port)=0
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
virtual SandeshResponse * Alloc()=0
void set_context(std::string context)
Definition: p/sandesh.h:310
virtual KSyncObject * GetObject(OvsdbClientSession *session)=0
void SandeshError(const std::string &msg, const std::string &context)
Definition: dns_mgr.cc:781
virtual void EncodeArgs(AgentSandeshArguments &args)
Definition: ovsdb_sandesh.h:51
static const uint8_t kEntriesPerSandesh
Definition: ovsdb_sandesh.h:33
virtual FilterResp Filter(KSyncEntry *entry)
Definition: ovsdb_sandesh.h:52
Task is a wrapper over tbb::task to support policies.
Definition: task.h:86
virtual void set_more(const bool val)=0
virtual OvsdbClientSession * NextSession(OvsdbClientSession *session)=0
struct task_ task
int Decode(const std::string &str)
virtual void UpdateResp(KSyncEntry *entry, SandeshResponse *resp)=0
static const uint8_t kEntriesPerPage
Definition: ovsdb_sandesh.h:34