blob: 63776054326835388fdb33795a75f09c0190dcbc [file] [log] [blame]
HIGUCHI Yutaed49ef72013-06-12 11:34:10 -07001package net.onrc.onos.ofcontroller.core.internal;
Pankaj Berde3200ea02013-01-04 15:48:36 -08002
Pavlin Radoslavov64647d22013-11-04 19:07:03 -08003import java.util.ArrayList;
4import java.util.List;
5
Pankaj Berdebbd38612013-06-22 05:59:12 -07006import net.floodlightcontroller.core.IOFSwitch;
Pankaj Berde38646d62013-06-21 11:34:04 -07007import net.onrc.onos.graph.GraphDBConnection;
8import net.onrc.onos.graph.GraphDBOperation;
HIGUCHI Yuta20514902013-06-12 11:24:16 -07009import net.onrc.onos.ofcontroller.core.ISwitchStorage;
10import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
11import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
Pankaj Berdeafb20532013-01-08 15:05:24 -080012
Pankaj Berde3200ea02013-01-04 15:48:36 -080013import org.openflow.protocol.OFPhysicalPort;
Pankaj Berde6a4075d2013-01-22 16:42:54 -080014import org.openflow.protocol.OFPhysicalPort.OFPortConfig;
15import org.openflow.protocol.OFPhysicalPort.OFPortState;
Pankaj Berde15193092013-03-21 17:30:14 -070016import org.slf4j.Logger;
17import org.slf4j.LoggerFactory;
Pankaj Berde3200ea02013-01-04 15:48:36 -080018
Teruef33dc32013-06-20 09:54:37 -070019/**
Naoki Shiota987a5722013-10-23 11:59:36 -070020 * This is the class for storing the information of switches into GraphDB
Teruef33dc32013-06-20 09:54:37 -070021 */
Pankaj Berde3200ea02013-01-04 15:48:36 -080022public class SwitchStorageImpl implements ISwitchStorage {
Toshio Koide4f3d9eb2013-06-13 13:20:55 -070023 protected GraphDBOperation op;
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070024 protected final static Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
Teruef33dc32013-06-20 09:54:37 -070025
26 /***
27 * Initialize function. Before you use this class, please call this method
28 * @param conf configuration file for Cassandra DB
29 */
Pankaj Berde3200ea02013-01-04 15:48:36 -080030 @Override
Teruef33dc32013-06-20 09:54:37 -070031 public void init(String conf) {
32 GraphDBConnection conn = GraphDBConnection.getInstance(conf);
33 op = new GraphDBOperation(conn);
34 }
Pankaj Berde3200ea02013-01-04 15:48:36 -080035
Teruef33dc32013-06-20 09:54:37 -070036 /***
37 * Finalize/close function. After you use this class, please call this method.
38 * It will close the DB connection.
39 */
40 public void finalize() {
41 close();
42 }
43
44 /***
45 * Finalize/close function. After you use this class, please call this method.
Pavlin Radoslavovef0cb002013-06-21 14:55:23 -070046 * It will close the DB connection. This is for Java garbage collection.
Teruef33dc32013-06-20 09:54:37 -070047 */
48 @Override
49 public void close() {
50 op.close();
51 }
52
Naoki Shiota987a5722013-10-23 11:59:36 -070053 // Method designing policy:
54 // op.commit() and op.rollback() MUST called in public (first-class) methods.
55 // A first-class method MUST NOT call other first-class method.
56 // Routine process should be implemented in private method.
57 // A private method MUST NOT call commit or rollback.
58
Teruef33dc32013-06-20 09:54:37 -070059 /***
Teruef33dc32013-06-20 09:54:37 -070060 * This function is for updating the switch into the DB.
61 * @param dpid The switch dpid you want to update from the DB
62 * @param state The state of the switch like ACTIVE, INACTIVE
63 * @param dmope The DM_OPERATION of the switch
64 */
Jonathan Hartadc63892013-11-08 14:03:55 -080065 /*
66 * Jono, 11/8/2013
67 * We don't need this update method that demultiplexes DM_OPERATIONS,
68 * we can have clients just call the required methods directly.
69 * We especially don't need this update method to re-implement
70 * the functions of other methods.
71 */
72 @Deprecated
Teruef33dc32013-06-20 09:54:37 -070073 @Override
Naoki Shiota987a5722013-10-23 11:59:36 -070074 public boolean updateSwitch(String dpid, SwitchState state, DM_OPERATION dmope) {
75 boolean success = false;
76 ISwitchObject sw = null;
77
78 log.info("SwitchStorage:update {} dpid:{}", dmope, dpid);
Naoki Shiotab2d17e82013-10-18 18:08:16 -070079 switch(dmope) {
80 case UPDATE:
Naoki Shiota987a5722013-10-23 11:59:36 -070081 try {
82 sw = op.searchSwitch(dpid);
83 if (sw != null) {
84 setSwitchStateImpl(sw, state);
85 op.commit();
86 success = true;
87 }
88 } catch (Exception e) {
89 op.rollback();
90 e.printStackTrace();
91 log.info("SwitchStorage:update {} dpid:{} failed", dmope, dpid);
92 }
93 break;
Naoki Shiotab2d17e82013-10-18 18:08:16 -070094 case INSERT:
95 case CREATE:
Naoki Shiota987a5722013-10-23 11:59:36 -070096 try {
97 sw = addSwitchImpl(dpid);
98 if (sw != null) {
99 if (state != SwitchState.ACTIVE) {
100 setSwitchStateImpl(sw, state);
101 }
102 op.commit();
103 success = true;
104 }
105 } catch (Exception e) {
106 op.rollback();
107 e.printStackTrace();
108 log.info("SwitchStorage:update {} dpid:{} failed", dmope, dpid);
109 }
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700110 break;
111 case DELETE:
Naoki Shiota987a5722013-10-23 11:59:36 -0700112 try {
113 sw = op.searchSwitch(dpid);
114 if (sw != null) {
115 deleteSwitchImpl(sw);
116 op.commit();
117 success = true;
118 }
119 } catch (Exception e) {
120 op.rollback();
121 e.printStackTrace();
122 log.info("SwitchStorage:update {} dpid:{} failed", dmope, dpid);
123 }
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700124 break;
125 default:
126 }
Naoki Shiota987a5722013-10-23 11:59:36 -0700127
128 return success;
129 }
130
131 @Override
132 public boolean addSwitch(IOFSwitch sw) {
133 boolean success = false;
134
135 String dpid = sw.getStringId();
136 log.info("SwitchStorage:addSwitch(): dpid {} ", dpid);
137
138 try {
139 ISwitchObject curr = op.searchSwitch(dpid);
140 if (curr != null) {
141 //If existing the switch. set The SW state ACTIVE.
142 log.info("SwitchStorage:addSwitch dpid:{} already exists", dpid);
143 setSwitchStateImpl(curr, SwitchState.ACTIVE);
144 } else {
145 curr = addSwitchImpl(dpid);
146 }
147
148 for (OFPhysicalPort port: sw.getPorts()) {
149 IPortObject p = op.searchPort(dpid, port.getPortNumber());
150 if (p != null) {
Jonathan Hart13ccdca2013-10-30 15:23:28 -0700151 log.debug("SwitchStorage:addPort dpid:{} port:{} exists", dpid, port.getPortNumber());
Naoki Shiota987a5722013-10-23 11:59:36 -0700152 setPortStateImpl(p, port.getState(), port.getName());
153 p.setState("ACTIVE");
Jonathan Hart13ccdca2013-10-30 15:23:28 -0700154 if (curr.getPort(port.getPortNumber()) == null) {
155 // The port exists but the switch has no "on" link to it
156 curr.addPort(p);
157 }
Naoki Shiota987a5722013-10-23 11:59:36 -0700158 } else {
159 p = addPortImpl(curr, port.getPortNumber());
160 setPortStateImpl(p, port.getState(), port.getName());
161 }
162 }
163 op.commit();
164 success = true;
165 } catch (Exception e) {
166 op.rollback();
Jonathan Hart13ccdca2013-10-30 15:23:28 -0700167 //e.printStackTrace();
168 log.error("SwitchStorage:addSwitch dpid:{} failed: {}", dpid);
169 log.error("switch write error", e);
Naoki Shiota987a5722013-10-23 11:59:36 -0700170 }
171
172 return success;
173 }
174
175 /***
176 * This function is for adding the switch into the DB.
177 * @param dpid The switch dpid you want to add into the DB.
178 */
Jonathan Hart13ccdca2013-10-30 15:23:28 -0700179 // This method is only called by tests, so we probably don't need it.
180 // If we need both addSwitch interfaces, one should call the other
181 // rather than implementing the same logic twice.
182 @Deprecated
Naoki Shiota987a5722013-10-23 11:59:36 -0700183 @Override
184 public boolean addSwitch(String dpid) {
185 boolean success = false;
186
187 log.info("SwitchStorage:addSwitch(): dpid {} ", dpid);
188 try {
189 ISwitchObject sw = op.searchSwitch(dpid);
190 if (sw != null) {
191 //If existing the switch. set The SW state ACTIVE.
192 log.info("SwitchStorage:addSwitch dpid:{} already exists", dpid);
193 setSwitchStateImpl(sw, SwitchState.ACTIVE);
194 } else {
195 addSwitchImpl(dpid);
196 }
197 op.commit();
198 success = true;
199 } catch (Exception e) {
200 op.rollback();
201 e.printStackTrace();
Jonathan Hartadc63892013-11-08 14:03:55 -0800202 log.error("SwitchStorage:addSwitch dpid:{} failed", dpid, e);
Naoki Shiota987a5722013-10-23 11:59:36 -0700203 }
204
205 return success;
206 }
207
208 /***
209 * This function is for deleting the switch into the DB.
210 * @param dpid The switch dpid you want to delete from the DB.
211 */
212 @Override
213 public boolean deleteSwitch(String dpid) {
214 boolean success = false;
215
216 try {
217 ISwitchObject sw = op.searchSwitch(dpid);
218 if (sw != null) {
219 deleteSwitchImpl(sw);
220 op.commit();
221 }
222 success = true;
223 } catch (Exception e) {
224 op.rollback();
225 e.printStackTrace();
226 log.error("SwitchStorage:deleteSwitch {} failed", dpid);
227 }
228
229 return success;
230 }
Jonathan Hartadc63892013-11-08 14:03:55 -0800231
232 public boolean deactivateSwitch(String dpid) {
233 boolean success = false;
234
235 try {
236 ISwitchObject switchObject = op.searchSwitch(dpid);
237 if (switchObject != null) {
238 setSwitchStateImpl(switchObject, SwitchState.INACTIVE);
239
240 for (IPortObject portObject : switchObject.getPorts()) {
241 portObject.setState("INACTIVE");
242 }
243 op.commit();
244 success = true;
245 }
246 else {
247 log.warn("Switch {} not found when trying to deactivate", dpid);
248 }
249 } catch (Exception e) {
250 // TODO what type of exception is thrown when we can't commit?
251 op.rollback();
252 log.error("SwitchStorage:deactivateSwitch {} failed", dpid, e);
253 }
254
255 return success;
256 }
Naoki Shiota987a5722013-10-23 11:59:36 -0700257
258 public boolean updatePort(String dpid, short portNum, int state, String desc) {
259 boolean success = false;
260
261 try {
262 ISwitchObject sw = op.searchSwitch(dpid);
263
264 if (sw != null) {
265 IPortObject p = sw.getPort(portNum);
266 log.info("SwitchStorage:updatePort dpid:{} port:{}", dpid, portNum);
267 if (p != null) {
268 setPortStateImpl(p, state, desc);
Pavlin Radoslavove86bbfc2013-11-05 08:32:14 -0800269 op.commit();
Naoki Shiota987a5722013-10-23 11:59:36 -0700270 }
Naoki Shiota987a5722013-10-23 11:59:36 -0700271 success = true;
272 } else {
273 log.error("SwitchStorage:updatePort dpid:{} port:{} : failed switch does not exist", dpid, portNum);
274 }
275 } catch (Exception e) {
276 op.rollback();
277 e.printStackTrace();
278 log.error("SwitchStorage:addPort dpid:{} port:{} failed", dpid, portNum);
279 }
280
281 return success;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700282 }
283
284 /***
285 * This function is for adding the switch port into the DB.
286 * @param dpid The switch dpid that has the port.
Naoki Shiota987a5722013-10-23 11:59:36 -0700287 * @param phport The port you want to add the switch.
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700288 */
289 @Override
Naoki Shiota987a5722013-10-23 11:59:36 -0700290 public boolean addPort(String dpid, OFPhysicalPort phport) {
291 boolean success = false;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700292
Naoki Shiota987a5722013-10-23 11:59:36 -0700293 if(((OFPortConfig.OFPPC_PORT_DOWN.getValue() & phport.getConfig()) > 0) ||
294 ((OFPortState.OFPPS_LINK_DOWN.getValue() & phport.getState()) > 0)) {
295 // just dispatch to deletePort()
Jonathan Hartadc63892013-11-08 14:03:55 -0800296 // TODO This is wrong. We need to make sure the port is in the
297 // DB with the correct info and port state.
Naoki Shiota987a5722013-10-23 11:59:36 -0700298 return deletePort(dpid, phport.getPortNumber());
299 }
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700300
301 try {
302 ISwitchObject sw = op.searchSwitch(dpid);
303
304 if (sw != null) {
Naoki Shiota987a5722013-10-23 11:59:36 -0700305 IPortObject p = sw.getPort(phport.getPortNumber());
306 log.info("SwitchStorage:addPort dpid:{} port:{}", dpid, phport.getPortNumber());
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700307 if (p != null) {
Naoki Shiota987a5722013-10-23 11:59:36 -0700308 setPortStateImpl(p, phport.getState(), phport.getName());
309 log.error("SwitchStorage:addPort dpid:{} port:{} exists setting as ACTIVE", dpid, phport.getPortNumber());
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700310 } else {
Naoki Shiota987a5722013-10-23 11:59:36 -0700311 addPortImpl(sw, phport.getPortNumber());
312 setPortStateImpl(p, phport.getState(), phport.getName());
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700313 }
Naoki Shiota987a5722013-10-23 11:59:36 -0700314 op.commit();
315 success = true;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700316 } else {
Naoki Shiota987a5722013-10-23 11:59:36 -0700317 log.error("SwitchStorage:addPort dpid:{} port:{} : failed switch does not exist", dpid, phport.getPortNumber());
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700318 }
319 } catch (Exception e) {
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700320 op.rollback();
Naoki Shiota987a5722013-10-23 11:59:36 -0700321 e.printStackTrace();
322 log.error("SwitchStorage:addPort dpid:{} port:{} failed", dpid, phport.getPortNumber());
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700323 }
Naoki Shiota987a5722013-10-23 11:59:36 -0700324
325 return success;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700326 }
327
328 /***
329 * This function is for deleting the switch port from the DB.
330 * @param dpid The switch dpid that has the port.
331 * @param port The port you want to delete the switch.
332 */
333 @Override
Naoki Shiota987a5722013-10-23 11:59:36 -0700334 public boolean deletePort(String dpid, short port) {
335 boolean success = false;
336
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700337 try {
338 ISwitchObject sw = op.searchSwitch(dpid);
339
340 if (sw != null) {
Naoki Shiota987a5722013-10-23 11:59:36 -0700341 IPortObject p = sw.getPort(port);
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700342 if (p != null) {
343 log.info("SwitchStorage:deletePort dpid:{} port:{} found and set INACTIVE", dpid, port);
Jonathan Hartadc63892013-11-08 14:03:55 -0800344 //deletePortImpl(p);
345 p.setState("INACTIVE");
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700346 op.commit();
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700347 }
348 }
Pavlin Radoslavov3d99e702013-11-04 15:39:34 -0800349 success = true;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700350 } catch (Exception e) {
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700351 op.rollback();
Naoki Shiota987a5722013-10-23 11:59:36 -0700352 e.printStackTrace();
Jonathan Hartadc63892013-11-08 14:03:55 -0800353 log.error("SwitchStorage:deletePort dpid:{} port:{} failed", dpid, port);
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700354 }
355
Naoki Shiota987a5722013-10-23 11:59:36 -0700356 return success;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700357 }
358
Pavlin Radoslavov64647d22013-11-04 19:07:03 -0800359 /**
360 * Get list of all ports on the switch specified by given DPID.
361 *
362 * @param dpid DPID of desired switch.
363 * @return List of port IDs. Empty list if no port was found.
364 */
365 @Override
366 public List<Short> getPorts(String dpid) {
367 List<Short> ports = new ArrayList<Short>();
368
369 ISwitchObject srcSw = op.searchSwitch(dpid);
370 if (srcSw != null) {
371 for (IPortObject srcPort : srcSw.getPorts()) {
372 ports.add(srcPort.getNumber());
373 }
374 }
375
376 return ports;
377 }
378
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700379 private ISwitchObject addSwitchImpl(String dpid) {
Naoki Shiota987a5722013-10-23 11:59:36 -0700380 if (dpid != null) {
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700381 ISwitchObject sw = op.newSwitch(dpid);
Naoki Shiota987a5722013-10-23 11:59:36 -0700382 sw.setState(SwitchState.ACTIVE.toString());
383 log.info("SwitchStorage:addSwitchImpl dpid:{} added", dpid);
384 return sw;
385 } else {
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700386 return null;
387 }
388 }
389
390 private void setSwitchStateImpl(ISwitchObject sw, SwitchState state) {
391 if (sw != null && state != null) {
392 sw.setState(state.toString());
Naoki Shiota987a5722013-10-23 11:59:36 -0700393 log.info("SwitchStorage:setSwitchStateImpl dpid:{} updated {}",
394 sw.getDPID(), state.toString());
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700395 }
Pankaj Berde3200ea02013-01-04 15:48:36 -0800396 }
Teruef33dc32013-06-20 09:54:37 -0700397
Naoki Shiota987a5722013-10-23 11:59:36 -0700398 private void deleteSwitchImpl(ISwitchObject sw) {
399 if (sw != null) {
400 op.removeSwitch(sw);
401 log.info("SwitchStorage:DeleteSwitchImpl dpid:{} done",
402 sw.getDPID());
403 }
404 }
405
Jonathan Hartd6ed62b2013-11-01 13:18:25 -0700406 // TODO There's an issue here where a port with that ID could already
407 // exist when we try to add this one (because it's left over from an
408 // old topology). We need to remove an old port with the same ID when
409 // we add the new port. Also it seems that old ports like this are
410 // never cleaned up and will remain in the DB in the ACTIVE state forever.
Naoki Shiota987a5722013-10-23 11:59:36 -0700411 private IPortObject addPortImpl(ISwitchObject sw, short portNum) {
412 IPortObject p = op.newPort(sw.getDPID(), portNum);
413 p.setState("ACTIVE");
414 sw.addPort(p);
415 log.info("SwitchStorage:addPortImpl dpid:{} port:{} done",
416 sw.getDPID(), portNum);
417
418 return p;
419 }
420
421 private void setPortStateImpl(IPortObject port, Integer state, String desc) {
422 if (port != null) {
423 if (state != null) {
424 port.setPortState(state);
425 }
426 if (desc != null) {
427 port.setDesc(desc);
428 }
429
430 log.info("SwitchStorage:setPortStateImpl port:{} state:{} desc:{} done",
431 new Object[] {port.getPortId(), state, desc});
432 }
433 }
434
435 private void deletePortImpl(IPortObject port) {
436 if (port != null) {
437 op.removePort(port);
438 log.info("SwitchStorage:deletePortImpl port:{} done",
439 port.getPortId());
440 }
441 }
Teru4fd58642013-06-21 07:54:49 -0700442}