OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
physical_device.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <boost/uuid/uuid_io.hpp>
6 #include <vnc_cfg_types.h>
7 #include <base/util.h>
8 
9 #include <ifmap/ifmap_node.h>
10 #include <cmn/agent_cmn.h>
11 #include <cfg/cfg_init.h>
12 #include <oper/agent_sandesh.h>
13 #include <oper/operdb_init.h>
14 #include <oper/config_manager.h>
16 
17 #include <oper/physical_device.h>
19 #include <oper/tunnel_nh.h>
20 
21 #include <vector>
22 #include <string>
23 #include <strings.h>
24 #include <multicast_types.h>
25 
26 using std::string;
27 using boost::assign::map_list_of;
28 using boost::assign::list_of;
29 
31 // PhysicalDevice routines
34  switch (proto) {
36  return "OVS";
37  break;
38 
39  default:
40  break;
41  }
42 
43  return "INVALID";
44 }
45 
46 static PhysicalDevice::ManagementProtocol FromString(const string &proto) {
47  if (strcasecmp(proto.c_str(), "ovs"))
48  return PhysicalDevice::OVS;
49 
51 }
52 
53 bool PhysicalDevice::IsLess(const DBEntry &rhs) const {
54  const PhysicalDevice &a =
55  static_cast<const PhysicalDevice &>(rhs);
56  return (uuid_ < a.uuid_);
57 }
58 
59 string PhysicalDevice::ToString() const {
60  return UuidToString(uuid_);
61 }
62 
65  return DBEntryBase::KeyPtr(key);
66 }
67 
69  const PhysicalDeviceKey *k = static_cast<const PhysicalDeviceKey *>(key);
70  uuid_ = k->uuid_;
71 }
72 
74  const PhysicalDeviceData *data) {
75  bool ret = false;
76  bool ip_updated = false;
77  IpAddress old_ip;
78 
79  if (fq_name_ != data->fq_name_) {
80  fq_name_ = data->fq_name_;
81  ret = true;
82  }
83 
84  if (name_ != data->name_) {
85  name_ = data->name_;
86  ret = true;
87  }
88 
89  if (vendor_ != data->vendor_) {
90  vendor_ = data->vendor_;
91  ret = true;
92  }
93 
94  if (ip_ != data->ip_) {
95  old_ip = ip_;
96  ip_updated = true;
97  ip_ = data->ip_;
98  ret = true;
99  }
100 
101  if (management_ip_ != data->management_ip_) {
103  ret = true;
104  }
105 
106  if (management_ip_ != data->management_ip_) {
108  ret = true;
109  }
110 
111  ManagementProtocol proto = FromString(data->protocol_);
112  if (protocol_ != proto) {
113  protocol_ = proto;
114  ret = true;
115  }
116 
117  if (ip_updated) {
118  table->UpdateIpToDevMap(old_ip, ip_, this);
119  }
120 
121  return ret;
122 }
123 
125 // PhysicalDeviceTable routines
127 std::unique_ptr<DBEntry> PhysicalDeviceTable::AllocEntry(const DBRequestKey *k)
128  const {
129  const PhysicalDeviceKey *key = static_cast<const PhysicalDeviceKey *>(k);
130  PhysicalDevice *dev = new PhysicalDevice(key->uuid_);
131  return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(dev));
132 }
133 
135  PhysicalDeviceKey *key = static_cast<PhysicalDeviceKey *>(req->key.get());
136  PhysicalDeviceData *data = static_cast<PhysicalDeviceData *>
137  (req->data.get());
138  PhysicalDevice *dev = new PhysicalDevice(key->uuid_);
139  dev->Copy(this, data);
140  dev->SendObjectLog(AgentLogEvent::ADD);
141  return dev;
142 }
143 
145  PhysicalDevice *dev = static_cast<PhysicalDevice *>(entry);
146  PhysicalDeviceData *data = dynamic_cast<PhysicalDeviceData *>
147  (req->data.get());
148  assert(data);
149  bool ret = dev->Copy(this, data);
150  dev->SendObjectLog(AgentLogEvent::CHANGE);
151  return ret;
152 }
153 
155  PhysicalDevice *dev = static_cast<PhysicalDevice *>(entry);
157  dynamic_cast<PhysicalDeviceTsnManagedData *>(req->data.get());
158  assert(data);
159  if (dev->master() != data->master_) {
160  dev->set_master(data->master_);
161  return true;
162  }
163  return false;
164 }
165 
167  PhysicalDevice *dev = static_cast<PhysicalDevice *>(entry);
168  DeleteIpToDevEntry(dev->ip());
169  dev->SendObjectLog(AgentLogEvent::DEL);
170  return true;
171 }
172 
174  PhysicalDeviceKey key(u);
175  return static_cast<PhysicalDevice *>(FindActiveEntry(&key));
176 }
177 
178 DBTableBase *PhysicalDeviceTable::CreateTable(DB *db, const std::string &name) {
179  PhysicalDeviceTable *table = new PhysicalDeviceTable(db, name);
180  table->Init();
181  return table;
182 }
183 
185 // Config handling
188 }
189 
190 static PhysicalDeviceKey *BuildKey(const autogen::PhysicalRouter
191  *router, const boost::uuids::uuid &u) {
192  return new PhysicalDeviceKey(u);
193 }
194 
196  const autogen::PhysicalRouter *router) {
197  boost::system::error_code ec;
198  IpAddress ip = IpAddress();
199  IpAddress mip = IpAddress();
200  ip = IpAddress::from_string(router->dataplane_ip(), ec);
201  mip = IpAddress::from_string(router->management_ip(), ec);
202  return new PhysicalDeviceData(agent, node->name(), router->display_name(),
203  router->vendor_name(), ip, mip, "OVS", node);
204 }
205 
207  autogen::PhysicalRouter *router = static_cast <autogen::PhysicalRouter *>
208  (node->GetObject());
209  autogen::IdPermsType id_perms = router->id_perms();
210  CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u);
211  return true;
212 }
213 
215  const boost::uuids::uuid &u) {
216  autogen::PhysicalRouter *router = static_cast <autogen::PhysicalRouter *>
217  (node->GetObject());
218  assert(router);
219 
220  req.key.reset(BuildKey(router, u));
221  if (node->IsDeleted()) {
223  return true;
224  }
225 
227  req.data.reset(BuildData(agent(), node, router));
228  Enqueue(&req);
229 
230  return false;
231 }
232 
234  const boost::uuids::uuid &u) {
235  autogen::PhysicalRouter *router = static_cast <autogen::PhysicalRouter *>
236  (node->GetObject());
237  assert(router);
238 
239  assert(!u.is_nil());
240 
241  req.key.reset(BuildKey(router, u));
242  if ((req.oper == DBRequest::DB_ENTRY_DELETE) || node->IsDeleted()) {
244  return true;
245  }
246 
248  return false;
249 }
250 
252 // Sandesh routines
254 class DeviceSandesh : public AgentSandesh {
255  public:
256  DeviceSandesh(std::string context, const std::string &name)
257  : AgentSandesh(context, name) {}
258 
259  private:
261  return static_cast<DBTable *>
263  }
264  void Alloc() {
265  resp_ = new SandeshDeviceListResp();
266  }
267 };
268 
269 static void SetDeviceSandeshData(const PhysicalDevice *entry,
270  SandeshDevice *data) {
271  data->set_uuid(UuidToString(entry->uuid()));
272  data->set_fq_name(entry->fq_name());
273  data->set_name(entry->name());
274  data->set_vendor(entry->vendor());
275  data->set_ip_address(entry->ip().to_string());
276  data->set_management_protocol(ToString(entry->protocol()));
277  data->set_master(entry->master());
278 }
279 
280 bool PhysicalDevice::DBEntrySandesh(Sandesh *resp, std::string &name)
281  const {
282  SandeshDeviceListResp *dev_resp =
283  static_cast<SandeshDeviceListResp *> (resp);
284 
285  std::string str_uuid = UuidToString(uuid_);
286  if (name.empty() || name_.find(name) != string::npos) {
287  SandeshDevice data;
288  SetDeviceSandeshData(this, &data);
289  std::vector<SandeshDevice> &list =
290  const_cast<std::vector<SandeshDevice>&>
291  (dev_resp->get_device_list());
292  list.push_back(data);
293  return true;
294  }
295 
296  return false;
297 }
298 
299 void SandeshDeviceReq::HandleRequest() const {
300  AgentSandeshPtr sand(new DeviceSandesh(context(), get_name()));
301  sand->DoSandesh(sand);
302 }
303 
305 (const AgentSandeshArguments *args, const std::string &context) {
306  return AgentSandeshPtr(new DeviceSandesh(context, args->GetString("name")));
307 }
308 
310  DeviceObjectLogInfo info;
311 
312  string str;
313  switch (event) {
314  case AgentLogEvent::ADD:
315  str.assign("Addition ");
316  break;
317  case AgentLogEvent::DEL:
318  str.assign("Deletion ");
319  break;
320  case AgentLogEvent::CHANGE:
321  str.assign("Modification ");
322  break;
323  default:
324  str.assign("INVALID");
325  break;
326  }
327  info.set_event(str);
328 
329  info.set_uuid(UuidToString(uuid_));
330  info.set_fq_name(fq_name_);
331  info.set_name(name_);
332  info.set_vendor(vendor_);
333  info.set_ip_address(ip_.to_string());
334  info.set_management_protocol(::ToString(protocol_));
335  info.set_ref_count(GetRefCount());
336  DEVICE_OBJECT_LOG_LOG("Device", SandeshLevel::SYS_INFO, info);
337 }
338 
340  PhysicalDevice *p) {
341  DeleteIpToDevEntry(old_ip);
342  if (!new_ip.is_unspecified()) {
343  IpToDeviceMap::iterator it = ip_tree_.find(new_ip);
344  if (it == ip_tree_.end()) {
345  ip_tree_.insert(IpToDevicePair(new_ip, p));
346  }
347  }
348 }
349 
351  if (!ip.is_unspecified()) {
352  IpToDeviceMap::iterator it = ip_tree_.find(ip);
353  if (it != ip_tree_.end()) {
354  ip_tree_.erase(it);
355  }
356  }
357 }
358 
360  if (!ip.is_unspecified()) {
361  IpToDeviceMap::iterator it = ip_tree_.find(ip);
362  if (it != ip_tree_.end()) {
363  return it->second;
364  }
365  }
366  return NULL;
367 }
368 
369 // Mastership changed for device, enqueue RESYNC to update master_ field if
370 // physical-device already present
372  bool master) {
374  req.key.reset(new PhysicalDeviceKey(u, AgentKey::RESYNC));
375 
376  req.data.reset(new PhysicalDeviceTsnManagedData(agent(), master));
377  Enqueue(&req);
378 }
379 
381  const std::string &vrf) {
382  DeviceVrfMap::iterator it = device2vrf_map_.find(u);
383  if (it == device2vrf_map_.end()) {
384  VrfSet vrf_set;
385  vrf_set.insert(vrf);
386  device2vrf_map_.insert(DeviceVrfPair(u, vrf_set));
387  return;
388  }
389  VrfSet &vrf_set = it->second;
390  VrfSet::iterator vit = vrf_set.find(vrf);
391  if (vit == vrf_set.end()) {
392  vrf_set.insert(vrf);
393  }
394 }
395 
396 /* Removes VRF from the vrf_list to which the device points. If the device does
397  * not point to any more VRFs, then the device entry itself is removed. If the
398  * device entry itself is removed or if the device is absent in the list, it
399  * returns true. */
401  const std::string &vrf) {
402  DeviceVrfMap::iterator it = device2vrf_map_.find(u);
403  if (it == device2vrf_map_.end()) {
404  return true;
405  }
406  VrfSet &vrf_set = it->second;
407  VrfSet::iterator vit = vrf_set.find(vrf);
408  if (vit == vrf_set.end()) {
409  return false;
410  }
411  /* If the VRF to be removed is the only vrf to which the device points,
412  * then remove the device itself */
413  if (vrf_set.size() == 1) {
414  device2vrf_map_.erase(it);
415  return true;
416  }
417  vrf_set.erase(vit);
418  return false;
419 }
420 
422  const std::string &vrf) {
423  if (!RemoveDeviceToVrfEntry(u, vrf)) {
424  /* If the device is pointing to any other vrfs apart from the
425  * one passed to this API, then we still need to have
426  * mastership as true for that device */
427  return;
428  }
429  PhysicalDeviceSet::iterator dit = managed_pd_set_.find(u);
430  if (dit != managed_pd_set_.end()) {
431  /* Update mastership as false for the device */
432  EnqueueDeviceChange(u, false);
433  managed_pd_set_.erase(dit);
434  }
435 }
436 
438  ComponentNHList clist,
439  bool del) {
440  PhysicalDeviceSet new_set;
441 
442  if (del) {
443  VrfDevicesMap::iterator it = vrf2devices_map_.find(vrf);
444  if (it == vrf2devices_map_.end()) {
445  return;
446  }
447  PhysicalDeviceSet dev_set = it->second;
448  PhysicalDeviceSet::iterator pit = dev_set.begin();
449  while (pit != dev_set.end()) {
450  ResetDeviceMastership(*pit, vrf);
451  ++pit;
452  }
453  vrf2devices_map_.erase(it);
454  return;
455  }
456 
457  ComponentNHList::const_iterator comp_nh_it = clist.begin();
458  for(;comp_nh_it != clist.end(); comp_nh_it++) {
459  if ((*comp_nh_it) == NULL) {
460  continue;
461  }
462 
463  if ((*comp_nh_it)->nh()->GetType() != NextHop::TUNNEL) {
464  continue;
465  }
466  const TunnelNH *tnh = static_cast<const TunnelNH *>
467  ((*comp_nh_it)->nh());
468 
469  PhysicalDevice *dev = IpToPhysicalDevice(*(tnh->GetDip()));
470  if (dev == NULL) {
471  continue;
472  }
473  AddDeviceToVrfEntry(dev->uuid(), vrf);
474  /* Enqueue the change as true only if it was not earlier enqueued.
475  * List of previously enqueued devices (with master as true) is
476  * present in managed_pd_set_ */
477  PhysicalDeviceSet::iterator pit = managed_pd_set_.find(dev->uuid());
478  if (pit == managed_pd_set_.end()) {
479  EnqueueDeviceChange(dev->uuid(), true);
480  managed_pd_set_.insert(dev->uuid());
481  }
482  new_set.insert(dev->uuid());
483  }
484 
485  /* Iterate through the old per vrf physical device list. If any of them are
486  * not present in new list, enqueue change on those devices with master
487  * as false */
488  VrfDevicesMap::iterator it = vrf2devices_map_.find(vrf);
489  if (it == vrf2devices_map_.end()) {
490  vrf2devices_map_.insert(VrfDevicesPair(vrf, new_set));
491  return;
492  }
493  PhysicalDeviceSet dev_set = it->second;
494  PhysicalDeviceSet::iterator pit = dev_set.begin();
495  while (pit != dev_set.end()) {
496  const boost::uuids::uuid &u = *pit;
497  ++pit;
498  PhysicalDeviceSet::iterator dit = new_set.find(u);
499  if (dit == new_set.end()) {
500  /* This means that physical-device 'u' is removed from vrf passed
501  * to this API. Reset the mastership only if the physical-device
502  * is not present for any other VRFs */
503  ResetDeviceMastership(u, vrf);
504  }
505  }
506  //Update the devices_set for the vrf with new_set
507  it->second = new_set;
508 }
509 
510 void MasterPhysicalDevicesReq::HandleRequest() const {
511  MasterPhysicalDevicesResp *resp = new MasterPhysicalDevicesResp();
512  resp->set_context(context());
513 
514  Agent *agent = Agent::GetInstance();
517  obj->managed_pd_set();
518  PhysicalDeviceTable::PhysicalDeviceSet::const_iterator it =
519  dev_list.begin();
520  std::vector<PDeviceData> list;
521  while (it != dev_list.end()) {
522  PDeviceData data;
523  data.set_uuid(to_string(*it));
524  list.push_back(data);
525  ++it;
526  }
527  resp->set_dev_list(list);
528  resp->set_more(false);
529  resp->Response();
530 }
virtual bool OperDBDelete(DBEntry *entry, const DBRequest *req)
void SendObjectLog(AgentLogEvent::type event) const
ManagementProtocol protocol() const
const std::string & vendor() const
static Agent * GetInstance()
Definition: agent.h:436
static void CfgUuidSet(uint64_t ms_long, uint64_t ls_long, boost::uuids::uuid &u)
Definition: agent_cmn.h:67
virtual void SetKey(const DBRequestKey *key)
void UpdateDeviceMastership(const std::string &vrf, ComponentNHList clist, bool del)
DeviceVrfMap device2vrf_map_
void UpdateIpToDevMap(IpAddress old, IpAddress new_ip, PhysicalDevice *p)
virtual KeyPtr GetDBRequestKey() const
std::string GetString(const std::string &key) const
std::string fq_name_
static DBTableBase * CreateTable(DB *db, const std::string &name)
const PhysicalDeviceSet & managed_pd_set() const
std::set< boost::uuids::uuid > PhysicalDeviceSet
PhysicalDeviceSet managed_pd_set_
PhysicalDeviceTable * physical_device_table() const
Definition: agent.h:628
bool IsDeleted() const
Definition: db_entry.h:49
ConfigManager * config_manager() const
Definition: agent.cc:889
boost::asio::ip::address IpAddress
Definition: address.h:13
Agent * agent() const
Definition: agent_db.h:213
std::pair< const boost::uuids::uuid, VrfSet > DeviceVrfPair
VrfDevicesMap vrf2devices_map_
std::unique_ptr< DBRequestData > data
Definition: db_table.h:49
std::string fq_name_
static PhysicalDeviceKey * BuildKey(const autogen::PhysicalRouter *router, const boost::uuids::uuid &u)
AgentDBEntry * FindActiveEntry(const DBEntry *key)
Definition: agent_db.cc:110
bool Enqueue(DBRequest *req)
Definition: db_table.cc:194
DBTable * AgentGetTable()
const Ip4Address * GetDip() const
Definition: tunnel_nh.h:37
boost::uuids::uuid uuid
virtual bool OperDBResync(DBEntry *entry, const DBRequest *req)
static std::string UuidToString(const boost::uuids::uuid &id)
Definition: string_util.h:138
void RegisterDBClients(IFMapDependencyManager *dep)
const boost::uuids::uuid & uuid() const
bool DBEntrySandesh(Sandesh *resp, std::string &name) const
void EnqueueDeviceChange(const boost::uuids::uuid &u, bool master)
std::unique_ptr< DBRequestKey > KeyPtr
Definition: db_entry.h:25
const IpAddress & ip() const
virtual std::string ToString() const
virtual AgentSandeshPtr GetAgentSandesh(const AgentSandeshArguments *args, const std::string &context)
Definition: db.h:24
static string ToString(PhysicalDevice::ManagementProtocol proto)
PhysicalDevice * Find(const boost::uuids::uuid &u)
void Init()
Definition: db_table.cc:387
std::pair< const std::string, PhysicalDeviceSet > VrfDevicesPair
IpAddress management_ip_
void AddPhysicalDeviceNode(IFMapNode *node)
uint8_t type
Definition: load_balance.h:109
Definition: agent.h:358
void AddDeviceToVrfEntry(const boost::uuids::uuid &u, const std::string &vrf)
bool master() const
std::pair< IpAddress, PhysicalDevice * > IpToDevicePair
void set_master(bool value)
std::unique_ptr< DBRequestKey > key
Definition: db_table.h:48
DBOperation oper
Definition: db_table.h:42
boost::uuids::uuid uuid_
virtual std::unique_ptr< DBEntry > AllocEntry(const DBRequestKey *k) const
class boost::shared_ptr< AgentSandesh > AgentSandeshPtr
Definition: agent_db.h:18
boost::uuids::uuid uuid_
bool Copy(PhysicalDeviceTable *table, const PhysicalDeviceData *data)
const std::string & name() const
Definition: ifmap_node.h:48
bool RemoveDeviceToVrfEntry(const boost::uuids::uuid &u, const std::string &vrf)
static void SetDeviceSandeshData(const PhysicalDevice *entry, SandeshDevice *data)
const std::string & fq_name() const
static PhysicalDeviceData * BuildData(Agent *agent, IFMapNode *node, const autogen::PhysicalRouter *router)
PhysicalDevice * IpToPhysicalDevice(IpAddress ip)
IFMapObject * GetObject()
Definition: ifmap_node.cc:63
std::string protocol_
const std::string & name() const
bool ProcessConfig(IFMapNode *node, DBRequest &req, const boost::uuids::uuid &u)
virtual bool IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u)
std::vector< ComponentNHPtr > ComponentNHList
Definition: nexthop.h:1637
void DeleteIpToDevEntry(IpAddress ip)
virtual bool OperDBOnChange(DBEntry *entry, const DBRequest *req)
uint32_t GetRefCount() const
virtual bool IsLess(const DBEntry &rhs) const
ManagementProtocol protocol_
std::set< std::string > VrfSet
IpAddress management_ip_
std::string name_
std::string context() const
IpToDeviceMap ip_tree_
virtual DBEntry * OperDBAdd(const DBRequest *req)
SandeshResponse * resp_
static PhysicalDevice::ManagementProtocol FromString(const string &proto)
DeviceSandesh(std::string context, const std::string &name)
std::string vendor_
virtual bool IFNodeToReq(IFMapNode *node, DBRequest &req, const boost::uuids::uuid &u)
void ResetDeviceMastership(const boost::uuids::uuid &u, const std::string &vrf)
PhysicalDeviceTable(DB *db, const std::string &name)