Line data Source code
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>
14 : #include <oper/ifmap_dependency_manager.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 :
25 : /////////////////////////////////////////////////////////////////////////////
26 : // PhysicalInterface routines
27 : /////////////////////////////////////////////////////////////////////////////
28 0 : PhysicalInterface::PhysicalInterface(const std::string &name,
29 0 : const boost::uuids::uuid &logical_router_uuid) :
30 0 : Interface(Interface::PHYSICAL, boost::uuids::nil_uuid(), name, NULL, true,
31 : logical_router_uuid),
32 0 : persistent_(false), subtype_(INVALID), physical_device_(NULL) {
33 0 : }
34 :
35 0 : PhysicalInterface::~PhysicalInterface() {
36 0 : }
37 :
38 0 : PhysicalDevice *PhysicalInterface::physical_device() const {
39 0 : return physical_device_.get();
40 : }
41 :
42 0 : string PhysicalInterface::ToString() const {
43 0 : return "PORT <" + name() + ">";
44 : }
45 :
46 0 : bool PhysicalInterface::CmpInterface(const DBEntry &rhs) const {
47 0 : const PhysicalInterface &a = static_cast<const PhysicalInterface &>(rhs);
48 0 : return name() < a.name();
49 : }
50 :
51 0 : DBEntryBase::KeyPtr PhysicalInterface::GetDBRequestKey() const {
52 0 : InterfaceKey *key = new PhysicalInterfaceKey(name());
53 0 : return DBEntryBase::KeyPtr(key);
54 : }
55 :
56 0 : bool PhysicalInterface::OnChange(const InterfaceTable *table,
57 : const PhysicalInterfaceData *data) {
58 0 : bool ret = false;
59 : const PhysicalInterfaceOsOperStateData *osOperStateData =
60 0 : dynamic_cast<const PhysicalInterfaceOsOperStateData *>(data);
61 :
62 0 : if(osOperStateData) {
63 0 : ret = osOperStateData->OnResync(this);
64 : }
65 : else {
66 : // Handle VRF Change
67 0 : VrfKey key(data->vrf_name_);
68 0 : VrfEntry *new_vrf = static_cast<VrfEntry *>
69 0 : (table->agent()->vrf_table()->FindActiveEntry(&key));
70 0 : if (new_vrf != vrf_.get()) {
71 0 : vrf_.reset(new_vrf);
72 0 : ret = true;
73 :
74 : }
75 :
76 : PhysicalDevice *dev =
77 0 : table->agent()->physical_device_table()->Find(data->device_uuid_);
78 0 : if (dev != physical_device_.get()) {
79 0 : physical_device_.reset(dev);
80 0 : ret = true;
81 : }
82 0 : }
83 0 : return ret;
84 : }
85 :
86 : bool
87 0 : PhysicalInterfaceOsOperStateData::OnResync(PhysicalInterface *phy_intf) const
88 : {
89 0 : bool ret = false;
90 0 : if(type_ == PhysicalInterfaceOsOperStateData::VR_FABRIC) {
91 0 : if(phy_intf->os_params_.os_oper_state_ != oper_state_) {
92 0 : phy_intf->os_params_.os_oper_state_ = oper_state_;
93 0 : ret = true;
94 : }
95 0 : } else if(type_ == PhysicalInterfaceOsOperStateData::VR_BOND_SLAVES) {
96 0 : PhysicalInterface::Bond_ChildIntf bondIntf;
97 :
98 0 : bondIntf.intf_name = intf_name;
99 0 : bondIntf.intf_drv_name = intf_drv_name;
100 0 : bondIntf.intf_status = oper_state_;
101 : PhysicalInterface::BondChildIntfMap bond_childIntf_map =
102 0 : phy_intf->getBondChildIntfMap();
103 0 : bond_childIntf_map[intf_name] = bondIntf;
104 0 : phy_intf->setBondChildIntfMap(bond_childIntf_map);
105 0 : ret = true;
106 0 : }
107 :
108 0 : return ret;
109 : }
110 :
111 0 : bool PhysicalInterface::Delete(const DBRequest *req) {
112 0 : flow_key_nh_.reset();
113 0 : InterfaceNH::DeletePhysicalInterfaceNh(name(), mac());
114 0 : return true;
115 : }
116 :
117 0 : std::string PhysicalInterface::GetPhysicalInterfaceName() const {
118 0 : std::size_t pos = name().find_last_of(":");
119 0 : if (pos != string::npos) {
120 0 : return name().substr(pos + 1);
121 : }
122 0 : return name();
123 : }
124 :
125 0 : void PhysicalInterface::PostAdd() {
126 0 : InterfaceNH::CreatePhysicalInterfaceNh(name(), mac());
127 :
128 0 : InterfaceTable *table = static_cast<InterfaceTable *>(get_table());
129 0 : Agent *agent = table->agent();
130 :
131 0 : InterfaceNHKey key(new PhysicalInterfaceKey(name()), false, InterfaceNHFlags::INET4, mac());
132 : flow_key_nh_ = static_cast<InterfaceNH *>
133 0 : (agent->nexthop_table()->FindActiveEntry(&key));
134 0 : assert(flow_key_nh_);
135 :
136 :
137 0 : if (table->agent()->test_mode()) {
138 0 : return;
139 : }
140 :
141 0 : std::string interface_name = name();
142 : // Interfaces in VMWARE mode and having remote VMs
143 : // must be put into promiscuous mode
144 0 : if (subtype_ != VMWARE) {
145 0 : if (!table->agent()->server_gateway_mode() ||
146 0 : subtype_ == PhysicalInterface::FABRIC) {
147 0 : return;
148 : } else {
149 0 : interface_name = GetPhysicalInterfaceName();
150 : }
151 : }
152 :
153 0 : int fd = socket(AF_LOCAL, SOCK_STREAM, 0);
154 0 : assert(fd >= 0);
155 :
156 : struct ifreq ifr;
157 0 : memset(&ifr, 0, sizeof(ifr));
158 0 : strncpy(ifr.ifr_name, interface_name.c_str(), IF_NAMESIZE-1);
159 :
160 0 : if (ioctl(fd, SIOCGIFFLAGS, (void *)&ifr) < 0) {
161 0 : LOG(ERROR, "Error <" << errno << ": " << strerror(errno) <<
162 : "> setting promiscuous flag for interface <" << interface_name << ">");
163 0 : close(fd);
164 0 : return;
165 : }
166 :
167 0 : ifr.ifr_flags |= IFF_PROMISC;
168 0 : if (ioctl(fd, SIOCSIFFLAGS, (void *)&ifr) < 0) {
169 0 : LOG(ERROR, "Error <" << errno << ": " << strerror(errno) <<
170 : "> setting promiscuous flag for interface <" << interface_name << ">");
171 0 : close(fd);
172 0 : return;
173 : }
174 :
175 0 : close(fd);
176 :
177 0 : }
178 :
179 : /////////////////////////////////////////////////////////////////////////////
180 : // PhysicalInterfaceKey routines
181 : /////////////////////////////////////////////////////////////////////////////
182 0 : PhysicalInterfaceKey::PhysicalInterfaceKey(const std::string &name) :
183 : InterfaceKey(AgentKey::ADD_DEL_CHANGE, Interface::PHYSICAL,
184 0 : boost::uuids::nil_uuid(), name, false) {
185 0 : }
186 :
187 0 : PhysicalInterfaceKey::~PhysicalInterfaceKey() {
188 0 : }
189 :
190 0 : Interface *PhysicalInterfaceKey::AllocEntry(const InterfaceTable *table) const {
191 0 : return new PhysicalInterface(name_, boost::uuids::nil_uuid());
192 : }
193 :
194 0 : Interface *PhysicalInterfaceKey::AllocEntry(const InterfaceTable *table,
195 : const InterfaceData *data) const {
196 0 : PhysicalInterface *intf = new PhysicalInterface(name_,
197 0 : data->logical_router_uuid_);
198 0 : const PhysicalInterfaceData *phy_data =
199 : static_cast<const PhysicalInterfaceData *>(data);
200 0 : intf->encap_type_ = phy_data->encap_type_;
201 0 : intf->no_arp_ = phy_data->no_arp_;
202 0 : intf->subtype_ = phy_data->subtype_;
203 0 : intf->display_name_ = phy_data->display_name_;
204 0 : if (intf->subtype_ == PhysicalInterface::VMWARE ||
205 0 : intf->subtype_ == PhysicalInterface::CONFIG) {
206 0 : intf->persistent_ = true;
207 : }
208 :
209 0 : intf->OnChange(table, phy_data);
210 0 : return intf;
211 : }
212 :
213 0 : InterfaceKey *PhysicalInterfaceKey::Clone() const {
214 0 : return new PhysicalInterfaceKey(name_);
215 : }
216 :
217 : /////////////////////////////////////////////////////////////////////////////
218 : // PhysicalInterfaceData routines
219 : /////////////////////////////////////////////////////////////////////////////
220 0 : PhysicalInterfaceData::PhysicalInterfaceData(Agent *agent, IFMapNode *node,
221 : const string &vrf_name,
222 : PhysicalInterface::SubType subtype,
223 : PhysicalInterface::EncapType encap,
224 : bool no_arp,
225 : const boost::uuids::uuid &device_uuid,
226 : const string &display_name,
227 : const Ip4Address &ip,
228 0 : Interface::Transport transport) :
229 0 : InterfaceData(agent, node, transport), subtype_(subtype), encap_type_(encap),
230 0 : no_arp_(no_arp), device_uuid_(device_uuid), display_name_(display_name),
231 0 : ip_(ip) {
232 0 : EthInit(vrf_name);
233 0 : }
234 :
235 : /////////////////////////////////////////////////////////////////////////////
236 : // Config handling routines
237 : /////////////////////////////////////////////////////////////////////////////
238 0 : static PhysicalInterfaceKey *BuildKey(const std::string &name) {
239 0 : return new PhysicalInterfaceKey(name);
240 : }
241 :
242 0 : bool InterfaceTable::PhysicalInterfaceIFNodeToReq(IFMapNode *node,
243 : DBRequest &req,
244 : const boost::uuids::uuid &u) {
245 :
246 : // Enqueue request to config-manager if add/change
247 0 : if ((req.oper != DBRequest::DB_ENTRY_DELETE) &&
248 0 : (node->IsDeleted() == false)) {
249 0 : agent()->config_manager()->AddPhysicalInterfaceNode(node);
250 0 : return false;
251 : }
252 :
253 : autogen::PhysicalInterface *port =
254 0 : static_cast <autogen::PhysicalInterface *>(node->GetObject());
255 0 : assert(port);
256 :
257 : // Get the physical-router from FQDN
258 0 : string device = "";
259 0 : vector<string> elements;
260 0 : split(elements, node->name(), boost::is_any_of(":"), boost::token_compress_on);
261 0 : if (elements.size() == 3) {
262 0 : device = elements[1];
263 : }
264 :
265 0 : if (elements.size() == 3 && device != agent()->agent_name()) {
266 0 : if (RemotePhysicalInterfaceIFNodeToReq(node, req, u)) {
267 0 : Enqueue(&req);
268 : }
269 0 : return false;
270 : }
271 :
272 0 : req.key.reset(BuildKey(node->name()));
273 0 : req.oper = DBRequest::DB_ENTRY_DELETE;
274 0 : return true;
275 0 : }
276 :
277 0 : bool InterfaceTable::PhysicalInterfaceProcessConfig(IFMapNode *node,
278 : DBRequest &req, const boost::uuids::uuid &u) {
279 :
280 0 : if (node->IsDeleted()) {
281 0 : return false;
282 : }
283 :
284 : autogen::PhysicalInterface *port =
285 0 : static_cast <autogen::PhysicalInterface *>(node->GetObject());
286 0 : assert(port);
287 :
288 : // Get the physical-router from FQDN
289 0 : string device = "";
290 0 : vector<string> elements;
291 0 : split(elements, node->name(), boost::is_any_of(":"), boost::token_compress_on);
292 0 : if (elements.size() == 3) {
293 0 : device = elements[1];
294 : }
295 :
296 : // If physical-router does not match agent_name, treat as remote interface
297 0 : if (elements.size() == 3 && device != agent()->agent_name()) {
298 0 : return RemotePhysicalInterfaceIFNodeToReq(node, req, u);
299 : }
300 :
301 0 : req.key.reset(BuildKey(node->name()));
302 :
303 0 : boost::uuids::uuid dev_uuid = boost::uuids::nil_uuid();
304 : // Find link with physical-router adjacency
305 0 : IFMapNode *adj_node = NULL;
306 0 : adj_node = agent()->config_manager()->FindAdjacentIFMapNode(node,
307 : "physical-router");
308 0 : if (adj_node) {
309 : autogen::PhysicalRouter *router =
310 0 : static_cast<autogen::PhysicalRouter *>(adj_node->GetObject());
311 0 : autogen::IdPermsType id_perms = router->id_perms();
312 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
313 : dev_uuid);
314 0 : }
315 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
316 0 : req.data.reset(new PhysicalInterfaceData(agent(), node,
317 0 : agent()->fabric_vrf_name(),
318 : PhysicalInterface::CONFIG,
319 : PhysicalInterface::ETHERNET,
320 : false, dev_uuid,
321 0 : port->display_name(),
322 0 : Ip4Address(0),
323 0 : Interface::TRANSPORT_ETHERNET));
324 0 : pi_ifnode_to_req_++;
325 0 : Enqueue(&req);
326 0 : return false;
327 0 : }
328 :
329 : /////////////////////////////////////////////////////////////////////////////
330 : // Utility methods
331 : /////////////////////////////////////////////////////////////////////////////
332 : // Enqueue DBRequest to create a Host Interface
333 0 : 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) {
339 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
340 0 : req.key.reset(new PhysicalInterfaceKey(ifname));
341 0 : req.data.reset(new PhysicalInterfaceData(NULL, NULL, vrf_name, subtype,
342 : encap, no_arp, device_uuid,
343 0 : ifname, ip, transport));
344 0 : table->Enqueue(&req);
345 0 : }
346 :
347 0 : 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) {
353 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
354 0 : req.key.reset(new PhysicalInterfaceKey(ifname));
355 0 : req.data.reset(new PhysicalInterfaceData(NULL, NULL, vrf_name, subtype,
356 : encap, no_arp, device_uuid,
357 0 : ifname, ip, transport));
358 0 : table->Process(req);
359 0 : }
360 :
361 : // Enqueue DBRequest to delete a Host Interface
362 0 : void PhysicalInterface::DeleteReq(InterfaceTable *table, const string &ifname) {
363 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
364 0 : req.key.reset(new PhysicalInterfaceKey(ifname));
365 0 : req.data.reset(NULL);
366 0 : table->Enqueue(&req);
367 0 : }
368 :
369 0 : void PhysicalInterface::Delete(InterfaceTable *table, const string &ifname) {
370 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
371 0 : req.key.reset(new PhysicalInterfaceKey(ifname));
372 0 : req.data.reset(NULL);
373 0 : table->Process(req);
374 0 : }
|