blob: 7f0c2590a1dc6872673303ca07600ad45ed0d61c [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 */
65 @Override
Naoki Shiota987a5722013-10-23 11:59:36 -070066 public boolean updateSwitch(String dpid, SwitchState state, DM_OPERATION dmope) {
67 boolean success = false;
68 ISwitchObject sw = null;
69
70 log.info("SwitchStorage:update {} dpid:{}", dmope, dpid);
Naoki Shiotab2d17e82013-10-18 18:08:16 -070071 switch(dmope) {
72 case UPDATE:
Naoki Shiota987a5722013-10-23 11:59:36 -070073 try {
74 sw = op.searchSwitch(dpid);
75 if (sw != null) {
76 setSwitchStateImpl(sw, state);
77 op.commit();
78 success = true;
79 }
80 } catch (Exception e) {
81 op.rollback();
82 e.printStackTrace();
83 log.info("SwitchStorage:update {} dpid:{} failed", dmope, dpid);
84 }
85 break;
Naoki Shiotab2d17e82013-10-18 18:08:16 -070086 case INSERT:
87 case CREATE:
Naoki Shiota987a5722013-10-23 11:59:36 -070088 try {
89 sw = addSwitchImpl(dpid);
90 if (sw != null) {
91 if (state != SwitchState.ACTIVE) {
92 setSwitchStateImpl(sw, state);
93 }
94 op.commit();
95 success = true;
96 }
97 } catch (Exception e) {
98 op.rollback();
99 e.printStackTrace();
100 log.info("SwitchStorage:update {} dpid:{} failed", dmope, dpid);
101 }
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700102 break;
103 case DELETE:
Naoki Shiota987a5722013-10-23 11:59:36 -0700104 try {
105 sw = op.searchSwitch(dpid);
106 if (sw != null) {
107 deleteSwitchImpl(sw);
108 op.commit();
109 success = true;
110 }
111 } catch (Exception e) {
112 op.rollback();
113 e.printStackTrace();
114 log.info("SwitchStorage:update {} dpid:{} failed", dmope, dpid);
115 }
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700116 break;
117 default:
118 }
Naoki Shiota987a5722013-10-23 11:59:36 -0700119
120 return success;
121 }
122
123 @Override
124 public boolean addSwitch(IOFSwitch sw) {
125 boolean success = false;
126
127 String dpid = sw.getStringId();
128 log.info("SwitchStorage:addSwitch(): dpid {} ", dpid);
129
130 try {
131 ISwitchObject curr = op.searchSwitch(dpid);
132 if (curr != null) {
133 //If existing the switch. set The SW state ACTIVE.
134 log.info("SwitchStorage:addSwitch dpid:{} already exists", dpid);
135 setSwitchStateImpl(curr, SwitchState.ACTIVE);
136 } else {
137 curr = addSwitchImpl(dpid);
138 }
139
140 for (OFPhysicalPort port: sw.getPorts()) {
141 IPortObject p = op.searchPort(dpid, port.getPortNumber());
142 if (p != null) {
Jonathan Hart13ccdca2013-10-30 15:23:28 -0700143 log.debug("SwitchStorage:addPort dpid:{} port:{} exists", dpid, port.getPortNumber());
Naoki Shiota987a5722013-10-23 11:59:36 -0700144 setPortStateImpl(p, port.getState(), port.getName());
145 p.setState("ACTIVE");
Jonathan Hart13ccdca2013-10-30 15:23:28 -0700146 if (curr.getPort(port.getPortNumber()) == null) {
147 // The port exists but the switch has no "on" link to it
148 curr.addPort(p);
149 }
Naoki Shiota987a5722013-10-23 11:59:36 -0700150 } else {
151 p = addPortImpl(curr, port.getPortNumber());
152 setPortStateImpl(p, port.getState(), port.getName());
153 }
154 }
155 op.commit();
156 success = true;
157 } catch (Exception e) {
158 op.rollback();
Jonathan Hart13ccdca2013-10-30 15:23:28 -0700159 //e.printStackTrace();
160 log.error("SwitchStorage:addSwitch dpid:{} failed: {}", dpid);
161 log.error("switch write error", e);
Naoki Shiota987a5722013-10-23 11:59:36 -0700162 }
163
164 return success;
165 }
166
167 /***
168 * This function is for adding the switch into the DB.
169 * @param dpid The switch dpid you want to add into the DB.
170 */
Jonathan Hart13ccdca2013-10-30 15:23:28 -0700171 // This method is only called by tests, so we probably don't need it.
172 // If we need both addSwitch interfaces, one should call the other
173 // rather than implementing the same logic twice.
174 @Deprecated
Naoki Shiota987a5722013-10-23 11:59:36 -0700175 @Override
176 public boolean addSwitch(String dpid) {
177 boolean success = false;
178
179 log.info("SwitchStorage:addSwitch(): dpid {} ", dpid);
180 try {
181 ISwitchObject sw = op.searchSwitch(dpid);
182 if (sw != null) {
183 //If existing the switch. set The SW state ACTIVE.
184 log.info("SwitchStorage:addSwitch dpid:{} already exists", dpid);
185 setSwitchStateImpl(sw, SwitchState.ACTIVE);
186 } else {
187 addSwitchImpl(dpid);
188 }
189 op.commit();
190 success = true;
191 } catch (Exception e) {
192 op.rollback();
193 e.printStackTrace();
194 log.info("SwitchStorage:addSwitch dpid:{} failed", dpid);
195 }
196
197 return success;
198 }
199
200 /***
201 * This function is for deleting the switch into the DB.
202 * @param dpid The switch dpid you want to delete from the DB.
203 */
204 @Override
205 public boolean deleteSwitch(String dpid) {
206 boolean success = false;
207
208 try {
209 ISwitchObject sw = op.searchSwitch(dpid);
210 if (sw != null) {
211 deleteSwitchImpl(sw);
212 op.commit();
213 }
214 success = true;
215 } catch (Exception e) {
216 op.rollback();
217 e.printStackTrace();
218 log.error("SwitchStorage:deleteSwitch {} failed", dpid);
219 }
220
221 return success;
222 }
223
224 public boolean updatePort(String dpid, short portNum, int state, String desc) {
225 boolean success = false;
226
227 try {
228 ISwitchObject sw = op.searchSwitch(dpid);
229
230 if (sw != null) {
231 IPortObject p = sw.getPort(portNum);
232 log.info("SwitchStorage:updatePort dpid:{} port:{}", dpid, portNum);
233 if (p != null) {
234 setPortStateImpl(p, state, desc);
Pavlin Radoslavove86bbfc2013-11-05 08:32:14 -0800235 op.commit();
Naoki Shiota987a5722013-10-23 11:59:36 -0700236 }
Naoki Shiota987a5722013-10-23 11:59:36 -0700237 success = true;
238 } else {
239 log.error("SwitchStorage:updatePort dpid:{} port:{} : failed switch does not exist", dpid, portNum);
240 }
241 } catch (Exception e) {
242 op.rollback();
243 e.printStackTrace();
244 log.error("SwitchStorage:addPort dpid:{} port:{} failed", dpid, portNum);
245 }
246
247 return success;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700248 }
249
250 /***
251 * This function is for adding the switch port into the DB.
252 * @param dpid The switch dpid that has the port.
Naoki Shiota987a5722013-10-23 11:59:36 -0700253 * @param phport The port you want to add the switch.
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700254 */
255 @Override
Naoki Shiota987a5722013-10-23 11:59:36 -0700256 public boolean addPort(String dpid, OFPhysicalPort phport) {
257 boolean success = false;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700258
Naoki Shiota987a5722013-10-23 11:59:36 -0700259 if(((OFPortConfig.OFPPC_PORT_DOWN.getValue() & phport.getConfig()) > 0) ||
260 ((OFPortState.OFPPS_LINK_DOWN.getValue() & phport.getState()) > 0)) {
261 // just dispatch to deletePort()
262 return deletePort(dpid, phport.getPortNumber());
263 }
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700264
265 try {
266 ISwitchObject sw = op.searchSwitch(dpid);
267
268 if (sw != null) {
Naoki Shiota987a5722013-10-23 11:59:36 -0700269 IPortObject p = sw.getPort(phport.getPortNumber());
270 log.info("SwitchStorage:addPort dpid:{} port:{}", dpid, phport.getPortNumber());
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700271 if (p != null) {
Naoki Shiota987a5722013-10-23 11:59:36 -0700272 setPortStateImpl(p, phport.getState(), phport.getName());
273 log.error("SwitchStorage:addPort dpid:{} port:{} exists setting as ACTIVE", dpid, phport.getPortNumber());
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700274 } else {
Naoki Shiota987a5722013-10-23 11:59:36 -0700275 addPortImpl(sw, phport.getPortNumber());
276 setPortStateImpl(p, phport.getState(), phport.getName());
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700277 }
Naoki Shiota987a5722013-10-23 11:59:36 -0700278 op.commit();
279 success = true;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700280 } else {
Naoki Shiota987a5722013-10-23 11:59:36 -0700281 log.error("SwitchStorage:addPort dpid:{} port:{} : failed switch does not exist", dpid, phport.getPortNumber());
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700282 }
283 } catch (Exception e) {
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700284 op.rollback();
Naoki Shiota987a5722013-10-23 11:59:36 -0700285 e.printStackTrace();
286 log.error("SwitchStorage:addPort dpid:{} port:{} failed", dpid, phport.getPortNumber());
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700287 }
Naoki Shiota987a5722013-10-23 11:59:36 -0700288
289 return success;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700290 }
291
292 /***
293 * This function is for deleting the switch port from the DB.
294 * @param dpid The switch dpid that has the port.
295 * @param port The port you want to delete the switch.
296 */
297 @Override
Naoki Shiota987a5722013-10-23 11:59:36 -0700298 public boolean deletePort(String dpid, short port) {
299 boolean success = false;
300
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700301 try {
302 ISwitchObject sw = op.searchSwitch(dpid);
303
304 if (sw != null) {
Naoki Shiota987a5722013-10-23 11:59:36 -0700305 IPortObject p = sw.getPort(port);
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700306 if (p != null) {
307 log.info("SwitchStorage:deletePort dpid:{} port:{} found and set INACTIVE", dpid, port);
Naoki Shiota987a5722013-10-23 11:59:36 -0700308 deletePortImpl(p);
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700309 op.commit();
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700310 }
311 }
Pavlin Radoslavov3d99e702013-11-04 15:39:34 -0800312 success = true;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700313 } catch (Exception e) {
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700314 op.rollback();
Naoki Shiota987a5722013-10-23 11:59:36 -0700315 e.printStackTrace();
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700316 log.info("SwitchStorage:deletePort dpid:{} port:{} failed", dpid, port);
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700317 }
318
Naoki Shiota987a5722013-10-23 11:59:36 -0700319 return success;
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700320 }
321
Pavlin Radoslavov64647d22013-11-04 19:07:03 -0800322 /**
323 * Get list of all ports on the switch specified by given DPID.
324 *
325 * @param dpid DPID of desired switch.
326 * @return List of port IDs. Empty list if no port was found.
327 */
328 @Override
329 public List<Short> getPorts(String dpid) {
330 List<Short> ports = new ArrayList<Short>();
331
332 ISwitchObject srcSw = op.searchSwitch(dpid);
333 if (srcSw != null) {
334 for (IPortObject srcPort : srcSw.getPorts()) {
335 ports.add(srcPort.getNumber());
336 }
337 }
338
339 return ports;
340 }
341
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700342 private ISwitchObject addSwitchImpl(String dpid) {
Naoki Shiota987a5722013-10-23 11:59:36 -0700343 if (dpid != null) {
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700344 ISwitchObject sw = op.newSwitch(dpid);
Naoki Shiota987a5722013-10-23 11:59:36 -0700345 sw.setState(SwitchState.ACTIVE.toString());
346 log.info("SwitchStorage:addSwitchImpl dpid:{} added", dpid);
347 return sw;
348 } else {
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700349 return null;
350 }
351 }
352
353 private void setSwitchStateImpl(ISwitchObject sw, SwitchState state) {
354 if (sw != null && state != null) {
355 sw.setState(state.toString());
Naoki Shiota987a5722013-10-23 11:59:36 -0700356 log.info("SwitchStorage:setSwitchStateImpl dpid:{} updated {}",
357 sw.getDPID(), state.toString());
Naoki Shiotab2d17e82013-10-18 18:08:16 -0700358 }
Pankaj Berde3200ea02013-01-04 15:48:36 -0800359 }
Teruef33dc32013-06-20 09:54:37 -0700360
Naoki Shiota987a5722013-10-23 11:59:36 -0700361 private void deleteSwitchImpl(ISwitchObject sw) {
362 if (sw != null) {
363 op.removeSwitch(sw);
364 log.info("SwitchStorage:DeleteSwitchImpl dpid:{} done",
365 sw.getDPID());
366 }
367 }
368
Jonathan Hartd6ed62b2013-11-01 13:18:25 -0700369 // TODO There's an issue here where a port with that ID could already
370 // exist when we try to add this one (because it's left over from an
371 // old topology). We need to remove an old port with the same ID when
372 // we add the new port. Also it seems that old ports like this are
373 // never cleaned up and will remain in the DB in the ACTIVE state forever.
Naoki Shiota987a5722013-10-23 11:59:36 -0700374 private IPortObject addPortImpl(ISwitchObject sw, short portNum) {
375 IPortObject p = op.newPort(sw.getDPID(), portNum);
376 p.setState("ACTIVE");
377 sw.addPort(p);
378 log.info("SwitchStorage:addPortImpl dpid:{} port:{} done",
379 sw.getDPID(), portNum);
380
381 return p;
382 }
383
384 private void setPortStateImpl(IPortObject port, Integer state, String desc) {
385 if (port != null) {
386 if (state != null) {
387 port.setPortState(state);
388 }
389 if (desc != null) {
390 port.setDesc(desc);
391 }
392
393 log.info("SwitchStorage:setPortStateImpl port:{} state:{} desc:{} done",
394 new Object[] {port.getPortId(), state, desc});
395 }
396 }
397
398 private void deletePortImpl(IPortObject port) {
399 if (port != null) {
400 op.removePort(port);
401 log.info("SwitchStorage:deletePortImpl port:{} done",
402 port.getPortId());
403 }
404 }
Teru4fd58642013-06-21 07:54:49 -0700405}