OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
physical_interface.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 <cmn/agent_cmn.h>
8 
9 #include <net/if.h>
10 #include <ifmap/ifmap_node.h>
11 #include <cfg/cfg_init.h>
12 #include <cfg/cfg_listener.h>
13 #include <oper/agent_sandesh.h>
15 #include <oper/interface_common.h>
16 #include <oper/physical_device.h>
17 #include <oper/nexthop.h>
18 #include <oper/config_manager.h>
19 
20 #include <vector>
21 #include <string>
22 
23 using std::string;
24 
26 // PhysicalInterface routines
28 PhysicalInterface::PhysicalInterface(const std::string &name,
29  const boost::uuids::uuid &logical_router_uuid) :
30  Interface(Interface::PHYSICAL, boost::uuids::nil_uuid(), name, NULL, true,
31  logical_router_uuid),
32  persistent_(false), subtype_(INVALID), physical_device_(NULL) {
33 }
34 
36 }
37 
39  return physical_device_.get();
40 }
41 
43  return "PORT <" + name() + ">";
44 }
45 
46 bool PhysicalInterface::CmpInterface(const DBEntry &rhs) const {
47  const PhysicalInterface &a = static_cast<const PhysicalInterface &>(rhs);
48  return name() < a.name();
49 }
50 
53  return DBEntryBase::KeyPtr(key);
54 }
55 
57  const PhysicalInterfaceData *data) {
58  bool ret = false;
59  const PhysicalInterfaceOsOperStateData *osOperStateData =
60  dynamic_cast<const PhysicalInterfaceOsOperStateData *>(data);
61 
62  if(osOperStateData) {
63  ret = osOperStateData->OnResync(this);
64  }
65  else {
66  // Handle VRF Change
67  VrfKey key(data->vrf_name_);
68  VrfEntry *new_vrf = static_cast<VrfEntry *>
69  (table->agent()->vrf_table()->FindActiveEntry(&key));
70  if (new_vrf != vrf_.get()) {
71  vrf_.reset(new_vrf);
72  ret = true;
73 
74  }
75 
76  PhysicalDevice *dev =
77  table->agent()->physical_device_table()->Find(data->device_uuid_);
78  if (dev != physical_device_.get()) {
79  physical_device_.reset(dev);
80  ret = true;
81  }
82  }
83  return ret;
84 }
85 
86 bool
88 {
89  bool ret = false;
91  if(phy_intf->os_params_.os_oper_state_ != oper_state_) {
93  ret = true;
94  }
97 
98  bondIntf.intf_name = intf_name;
99  bondIntf.intf_drv_name = intf_drv_name;
100  bondIntf.intf_status = oper_state_;
101  PhysicalInterface::BondChildIntfMap bond_childIntf_map =
102  phy_intf->getBondChildIntfMap();
103  bond_childIntf_map[intf_name] = bondIntf;
104  phy_intf->setBondChildIntfMap(bond_childIntf_map);
105  ret = true;
106  }
107 
108  return ret;
109 }
110 
112  flow_key_nh_.reset();
114  return true;
115 }
116 
118  std::size_t pos = name().find_last_of(":");
119  if (pos != string::npos) {
120  return name().substr(pos + 1);
121  }
122  return name();
123 }
124 
127 
128  InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
129  Agent *agent = table->agent();
130 
132  flow_key_nh_ = static_cast<InterfaceNH *>
133  (agent->nexthop_table()->FindActiveEntry(&key));
134  assert(flow_key_nh_);
135 
136 
137  if (table->agent()->test_mode()) {
138  return;
139  }
140 
141  std::string interface_name = name();
142  // Interfaces in VMWARE mode and having remote VMs
143  // must be put into promiscuous mode
144  if (subtype_ != VMWARE) {
145  if (!table->agent()->server_gateway_mode() ||
147  return;
148  } else {
149  interface_name = GetPhysicalInterfaceName();
150  }
151  }
152 
153  int fd = socket(AF_LOCAL, SOCK_STREAM, 0);
154  assert(fd >= 0);
155 
156  struct ifreq ifr;
157  memset(&ifr, 0, sizeof(ifr));
158  strncpy(ifr.ifr_name, interface_name.c_str(), IF_NAMESIZE-1);
159 
160  if (ioctl(fd, SIOCGIFFLAGS, (void *)&ifr) < 0) {
161  LOG(ERROR, "Error <" << errno << ": " << strerror(errno) <<
162  "> setting promiscuous flag for interface <" << interface_name << ">");
163  close(fd);
164  return;
165  }
166 
167  ifr.ifr_flags |= IFF_PROMISC;
168  if (ioctl(fd, SIOCSIFFLAGS, (void *)&ifr) < 0) {
169  LOG(ERROR, "Error <" << errno << ": " << strerror(errno) <<
170  "> setting promiscuous flag for interface <" << interface_name << ">");
171  close(fd);
172  return;
173  }
174 
175  close(fd);
176 
177 }
178 
180 // PhysicalInterfaceKey routines
183  InterfaceKey(AgentKey::ADD_DEL_CHANGE, Interface::PHYSICAL,
184  boost::uuids::nil_uuid(), name, false) {
185 }
186 
188 }
189 
191  return new PhysicalInterface(name_, boost::uuids::nil_uuid());
192 }
193 
195  const InterfaceData *data) const {
197  data->logical_router_uuid_);
198  const PhysicalInterfaceData *phy_data =
199  static_cast<const PhysicalInterfaceData *>(data);
200  intf->encap_type_ = phy_data->encap_type_;
201  intf->no_arp_ = phy_data->no_arp_;
202  intf->subtype_ = phy_data->subtype_;
203  intf->display_name_ = phy_data->display_name_;
204  if (intf->subtype_ == PhysicalInterface::VMWARE ||
206  intf->persistent_ = true;
207  }
208 
209  intf->OnChange(table, phy_data);
210  return intf;
211 }
212 
214  return new PhysicalInterfaceKey(name_);
215 }
216 
218 // PhysicalInterfaceData routines
221  const string &vrf_name,
224  bool no_arp,
225  const boost::uuids::uuid &device_uuid,
226  const string &display_name,
227  const Ip4Address &ip,
228  Interface::Transport transport) :
229  InterfaceData(agent, node, transport), subtype_(subtype), encap_type_(encap),
230  no_arp_(no_arp), device_uuid_(device_uuid), display_name_(display_name),
231  ip_(ip) {
232  EthInit(vrf_name);
233 }
234 
236 // Config handling routines
238 static PhysicalInterfaceKey *BuildKey(const std::string &name) {
239  return new PhysicalInterfaceKey(name);
240 }
241 
243  DBRequest &req,
244  const boost::uuids::uuid &u) {
245 
246  // Enqueue request to config-manager if add/change
247  if ((req.oper != DBRequest::DB_ENTRY_DELETE) &&
248  (node->IsDeleted() == false)) {
250  return false;
251  }
252 
253  autogen::PhysicalInterface *port =
254  static_cast <autogen::PhysicalInterface *>(node->GetObject());
255  assert(port);
256 
257  // Get the physical-router from FQDN
258  string device = "";
259  vector<string> elements;
260  split(elements, node->name(), boost::is_any_of(":"), boost::token_compress_on);
261  if (elements.size() == 3) {
262  device = elements[1];
263  }
264 
265  if (elements.size() == 3 && device != agent()->agent_name()) {
266  if (RemotePhysicalInterfaceIFNodeToReq(node, req, u)) {
267  Enqueue(&req);
268  }
269  return false;
270  }
271 
272  req.key.reset(BuildKey(node->name()));
274  return true;
275 }
276 
278  DBRequest &req, const boost::uuids::uuid &u) {
279 
280  if (node->IsDeleted()) {
281  return false;
282  }
283 
284  autogen::PhysicalInterface *port =
285  static_cast <autogen::PhysicalInterface *>(node->GetObject());
286  assert(port);
287 
288  // Get the physical-router from FQDN
289  string device = "";
290  vector<string> elements;
291  split(elements, node->name(), boost::is_any_of(":"), boost::token_compress_on);
292  if (elements.size() == 3) {
293  device = elements[1];
294  }
295 
296  // If physical-router does not match agent_name, treat as remote interface
297  if (elements.size() == 3 && device != agent()->agent_name()) {
298  return RemotePhysicalInterfaceIFNodeToReq(node, req, u);
299  }
300 
301  req.key.reset(BuildKey(node->name()));
302 
303  boost::uuids::uuid dev_uuid = boost::uuids::nil_uuid();
304  // Find link with physical-router adjacency
305  IFMapNode *adj_node = NULL;
306  adj_node = agent()->config_manager()->FindAdjacentIFMapNode(node,
307  "physical-router");
308  if (adj_node) {
309  autogen::PhysicalRouter *router =
310  static_cast<autogen::PhysicalRouter *>(adj_node->GetObject());
311  autogen::IdPermsType id_perms = router->id_perms();
312  CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
313  dev_uuid);
314  }
316  req.data.reset(new PhysicalInterfaceData(agent(), node,
317  agent()->fabric_vrf_name(),
320  false, dev_uuid,
321  port->display_name(),
322  Ip4Address(0),
325  Enqueue(&req);
326  return false;
327 }
328 
330 // Utility methods
332 // Enqueue DBRequest to create a Host Interface
333 void PhysicalInterface::CreateReq(InterfaceTable *table, const string &ifname,
334  const string &vrf_name, SubType subtype,
335  EncapType encap, bool no_arp,
336  const boost::uuids::uuid &device_uuid,
337  const Ip4Address &ip,
338  Interface::Transport transport) {
340  req.key.reset(new PhysicalInterfaceKey(ifname));
341  req.data.reset(new PhysicalInterfaceData(NULL, NULL, vrf_name, subtype,
342  encap, no_arp, device_uuid,
343  ifname, ip, transport));
344  table->Enqueue(&req);
345 }
346 
347 void PhysicalInterface::Create(InterfaceTable *table, const string &ifname,
348  const string &vrf_name, SubType subtype,
349  EncapType encap, bool no_arp,
350  const boost::uuids::uuid &device_uuid,
351  const Ip4Address &ip,
352  Interface::Transport transport) {
354  req.key.reset(new PhysicalInterfaceKey(ifname));
355  req.data.reset(new PhysicalInterfaceData(NULL, NULL, vrf_name, subtype,
356  encap, no_arp, device_uuid,
357  ifname, ip, transport));
358  table->Process(req);
359 }
360 
361 // Enqueue DBRequest to delete a Host Interface
362 void PhysicalInterface::DeleteReq(InterfaceTable *table, const string &ifname) {
364  req.key.reset(new PhysicalInterfaceKey(ifname));
365  req.data.reset(NULL);
366  table->Enqueue(&req);
367 }
368 
369 void PhysicalInterface::Delete(InterfaceTable *table, const string &ifname) {
371  req.key.reset(new PhysicalInterfaceKey(ifname));
372  req.data.reset(NULL);
373  table->Process(req);
374 }
PhysicalInterface::SubType subtype_
static void CfgUuidSet(uint64_t ms_long, uint64_t ls_long, boost::uuids::uuid &u)
Definition: agent_cmn.h:67
Definition: vrf.h:86
bool test_mode() const
Definition: agent.h:1191
PhysicalInterface(const std::string &name, const boost::uuids::uuid &logical_router_uuid)
void EthInit(const std::string &vrf_name)
Definition: interface.h:257
NextHopTable * nexthop_table() const
Definition: agent.h:475
DBTableBase * get_table() const
Definition: db_entry.cc:119
std::string GetPhysicalInterfaceName() const
friend struct PhysicalInterfaceKey
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
void AddPhysicalInterfaceNode(IFMapNode *node)
virtual bool OnResync(PhysicalInterface *phy_intf) const
std::unique_ptr< DBRequestData > data
Definition: db_table.h:49
AgentDBEntry * FindActiveEntry(const DBEntry *key)
Definition: agent_db.cc:110
bool Enqueue(DBRequest *req)
Definition: db_table.cc:194
boost::uuids::uuid uuid
const MacAddress & mac() const
Definition: interface.h:131
Agent * agent() const
Definition: interface.h:447
std::unique_ptr< DBRequestKey > KeyPtr
Definition: db_entry.h:25
virtual bool OnChange(const InterfaceTable *table, const PhysicalInterfaceData *data)
boost::uuids::uuid logical_router_uuid_
Definition: interface.h:267
std::string name_
Definition: interface.h:245
bool server_gateway_mode() const
Definition: agent.h:1168
bool PhysicalInterfaceProcessConfig(IFMapNode *node, DBRequest &req, const boost::uuids::uuid &u)
PhysicalDevice * Find(const boost::uuids::uuid &u)
IFMapNode * FindAdjacentIFMapNode(IFMapNode *node, const char *type)
Definition: agent.h:358
boost::uuids::uuid device_uuid_
std::string vrf_name_
Definition: interface.h:265
const BondChildIntfMap & getBondChildIntfMap() const
Definition: vrf.h:22
PhysicalDeviceRef physical_device_
static void Create(InterfaceTable *table, const std::string &ifname, const std::string &vrf_name, SubType subtype, EncapType encap, bool no_arp, const boost::uuids::uuid &device_uuid, const Ip4Address &ip, Interface::Transport transport_)
NextHopConstRef flow_key_nh_
Definition: interface.h:185
std::unique_ptr< DBRequestKey > key
Definition: db_table.h:48
DBOperation oper
Definition: db_table.h:42
virtual KeyPtr GetDBRequestKey() const
uint32_t pi_ifnode_to_req_
Definition: interface.h:497
bool PhysicalInterfaceIFNodeToReq(IFMapNode *node, DBRequest &req, const boost::uuids::uuid &u)
virtual void PostAdd()
virtual void Process(DBRequest &req)
Definition: agent_db.cc:231
const std::string & agent_name() const
Definition: agent.h:878
const std::string & name() const
Definition: ifmap_node.h:48
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
VrfTable * vrf_table() const
Definition: agent.h:485
void Delete()
Definition: db_entry.cc:131
IFMapObject * GetObject()
Definition: ifmap_node.cc:63
PhysicalInterfaceKey(const std::string &name)
PhysicalInterface::EncapType encap_type_
static void DeletePhysicalInterfaceNh(const string &ifname, const MacAddress &mac)
Definition: nexthop.cc:874
Interface * AllocEntry(const InterfaceTable *table) const
InterfaceKey * Clone() const
static PhysicalInterfaceKey * BuildKey(const std::string &name)
static void CreatePhysicalInterfaceNh(const string &ifname, const MacAddress &mac)
Definition: nexthop.cc:865
virtual bool CmpInterface(const DBEntry &rhs) const
void setBondChildIntfMap(const BondChildIntfMap bondChildIntfMap)
#define LOG(_Level, _Msg)
Definition: logging.h:33
VrfEntryRef vrf_
Definition: interface.h:163
static void DeleteReq(InterfaceTable *table, const std::string &ifname)
struct InterfaceOsParams os_params_
Definition: interface.h:188
const std::string & name() const
Definition: interface.h:114
PhysicalDevice * physical_device() const
virtual std::string ToString() const
bool RemotePhysicalInterfaceIFNodeToReq(IFMapNode *node, DBRequest &req, const boost::uuids::uuid &u)
std::map< const std::string, Bond_ChildIntf > BondChildIntfMap
PhysicalInterfaceData(Agent *agent, IFMapNode *node, const std::string &vrf_name, PhysicalInterface::SubType subtype, PhysicalInterface::EncapType encap, bool no_arp, const boost::uuids::uuid &device_uuid, const std::string &display_name, const Ip4Address &ip, Interface::Transport transport)
static void CreateReq(InterfaceTable *table, const std::string &ifname, const std::string &vrf_name, SubType subtype, EncapType encap, bool no_arp, const boost::uuids::uuid &device_uuid, const Ip4Address &ip, Interface::Transport transport)