blob: e4efc4ee447e77958f610daa05494feff95b539d [file] [log] [blame]
Jonathan Hart062a2e82014-02-03 09:41:57 -08001package net.onrc.onos.ofcontroller.networkgraph;
2
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -08003import java.util.NoSuchElementException;
4
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -08005import net.onrc.onos.datastore.topology.RCLink;
Jonathan Hart062a2e82014-02-03 09:41:57 -08006import net.onrc.onos.datastore.topology.RCPort;
7import net.onrc.onos.datastore.topology.RCSwitch;
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -08008import net.onrc.onos.ofcontroller.util.Dpid;
Jonathan Hart062a2e82014-02-03 09:41:57 -08009
10import org.slf4j.Logger;
11import org.slf4j.LoggerFactory;
12
13import edu.stanford.ramcloud.JRamCloud.ObjectDoesntExistException;
14
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080015/**
16 * The "NB" read-only Network Map.
17 *
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080018 * - Maintain Invariant/Relationships between Topology Objects.
19 *
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080020 * TODO To be synchronized based on TopologyEvent Notification.
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080021 *
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080022 * TODO TBD: This class may delay the requested change to handle event
23 * re-ordering. e.g.) Link Add came in, but Switch was not there.
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080024 */
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080025public class NetworkGraphImpl extends AbstractNetworkGraph {
Jonathan Hart062a2e82014-02-03 09:41:57 -080026
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080027 private static final Logger log = LoggerFactory
28 .getLogger(NetworkGraphImpl.class);
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080029
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080030 public NetworkGraphImpl() {
31 super();
32 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080033
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080034 /**
35 * Add Switch to Topology.
36 *
37 * Fails with an Exception if a switch with same DPID already exist in
38 * Topology.
39 *
40 * @param sw
41 */
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080042 void addSwitch(Switch sw) {
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080043 if (sw == null) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080044 throw new IllegalArgumentException("Switch cannot be null");
45 }
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080046 Switch oldSw = switches.putIfAbsent(sw.getDpid(), sw);
47 if (oldSw != null) {
48 // XXX Define or choose more appropriate Exception.
49 throw new RuntimeException("Switch already exists");
50 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080051 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080052
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080053 /**
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080054 * Deactivate and remove Switch.
55 *
56 * XXX Should it deactivate or delete its Ports also?
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080057 *
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080058 * @param sw
59 */
60 void deactivateSwitch(Switch sw) {
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080061 if (sw == null) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080062 throw new IllegalArgumentException("Switch cannot be null");
63 }
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -080064
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080065 if( !isSwitchInstanceInTopology(sw) ){
66 // XXX Define or choose more appropriate Exception.
67 throw new RuntimeException(
68 String.format(
69 "Switch with dpid %s did not exist or different instance registered.",
70 new Dpid(sw.getDpid())));
71 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080072
Yuta HIGUCHI80829d12014-02-05 20:16:56 -080073 // XXX Are we sure we want to deactivate Ports also?
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080074 for (Port p : sw.getPorts()) {
75 deactivatePort(p);
76 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080077
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -080078 // TODO Deactivate Switch: What to do simply remove?
79 for (Link l : sw.getIncomingLinks()) {
80 removeLink(l);
81 }
82
83 for (Link l : sw.getOutgoingLinks()) {
84 removeLink(l);
85 }
86
87 if (!switches.containsKey(sw.getDpid())) {
88 throw new NoSuchElementException(String.format(
89 "Switch with dpid %s not found.", new Dpid(sw.getDpid())));
90 }
91 boolean removed = switches.remove(sw.getDpid(), sw);
92
93 if (!removed) {
94 // XXX Define or choose more appropriate Exception.
95 throw new RuntimeException(
96 String.format(
97 "Switch with dpid %s did not exist or different instance registered.",
98 new Dpid(sw.getDpid())));
99 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800100 }
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -0800101
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800102 /**
103 * Add Port to Topology.
104 *
105 * @param port
106 */
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800107 void addPort(Port port) {
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800108 if (port == null) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800109 throw new IllegalArgumentException("Port cannot be null");
110 }
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800111 Switch sw = port.getSwitch();
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -0800112
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800113 if( !isSwitchInstanceInTopology(sw) ){
114 // XXX Define or choose more appropriate Exception.
115 throw new RuntimeException(
116 String.format(
117 "Switch with dpid %s did not exist or different instance registered.",
118 new Dpid(sw.getDpid())));
119 }
120
121 SwitchImpl s = getSwitchImpl(sw);
122
123 s.addPort(port);
124 // XXX Check If port already exist, if so then what? deactivate old?
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800125 }
126
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800127 /**
128 * Deactivate and remove Ports.
129 *
130 * @param port
131 */
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800132 void deactivatePort(Port port) {
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800133 if (port == null) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800134 throw new IllegalArgumentException("Port cannot be null");
135 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800136
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800137 Switch sw = port.getSwitch();
138
139 if( !isSwitchInstanceInTopology(sw) ){
140 // XXX Define or choose more appropriate Exception.
141 throw new RuntimeException(
142 String.format(
143 "Switch with dpid %s did not exist or different instance registered.",
144 new Dpid(sw.getDpid())));
145 }
146
147
148 // remove Link
149 removeLink(port.getIncomingLink());
150 removeLink(port.getOutgoingLink());
151
152 // remove Device
153 for(Device d: port.getDevices()) {
154 removeDevice(d);
155 }
156
157 // remove Port from Switch
158 SwitchImpl s = getSwitchImpl(sw);
159 s.removePort(port);
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800160 }
161
162 void addLink(Link link) {
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800163 if (link == null) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800164 throw new IllegalArgumentException("Link cannot be null");
165 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800166
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800167 Switch srcSw = link.getSourceSwitch();
168 if( !isSwitchInstanceInTopology(srcSw) ){
169 // XXX Define or choose more appropriate Exception.
170 throw new RuntimeException(
171 String.format(
172 "Switch with dpid %s did not exist or different instance registered.",
173 new Dpid(srcSw.getDpid())));
174 }
175
176 Switch dstSw = link.getDestinationSwitch();
177 if( !isSwitchInstanceInTopology(dstSw) ){
178 // XXX Define or choose more appropriate Exception.
179 throw new RuntimeException(
180 String.format(
181 "Switch with dpid %s did not exist or different instance registered.",
182 new Dpid(dstSw.getDpid())));
183 }
184
185 PortImpl srcPort = getPortImpl( link.getSourcePort() );
186 PortImpl dstPort = getPortImpl( link.getDestinationPort() );
187
188 // XXX check Existing Link first?
189 srcPort.setOutgoingLink(link);
190 dstPort.setIncomingLink(link);
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800191 }
192
193 void removeLink(Link link) {
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800194 if (link == null) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800195 throw new IllegalArgumentException("Link cannot be null");
196 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800197
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800198 Switch srcSw = link.getSourceSwitch();
199 if( !isSwitchInstanceInTopology(srcSw) ){
200 // XXX Define or choose more appropriate Exception.
201 throw new RuntimeException(
202 String.format(
203 "Switch with dpid %s did not exist or different instance registered.",
204 new Dpid(srcSw.getDpid())));
205 }
206
207 Switch dstSw = link.getDestinationSwitch();
208 if( !isSwitchInstanceInTopology(dstSw) ){
209 // XXX Define or choose more appropriate Exception.
210 throw new RuntimeException(
211 String.format(
212 "Switch with dpid %s did not exist or different instance registered.",
213 new Dpid(dstSw.getDpid())));
214 }
215
216 PortImpl srcPort = getPortImpl( link.getSourcePort() );
217 PortImpl dstPort = getPortImpl( link.getDestinationPort() );
218
219 // XXX check Existing Link first?
220 if( srcPort.getOutgoingLink() != link || dstPort.getIncomingLink() != link) {
221 // XXX Define or choose more appropriate Exception.
222 throw new RuntimeException(
223 String.format("Link %s did not belong to Topology", link.toString())
224 );
225 }
226 // remove Link
227 srcPort.setOutgoingLink(null);
228 dstPort.setIncomingLink(null);
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800229 }
230
231 void updateDevice(Device device) {
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800232 if (device == null) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800233 throw new IllegalArgumentException("Device cannot be null");
234 }
235 // TODO Auto-generated method stub
236
237 }
238
239 void removeDevice(Device device) {
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800240 if (device == null) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800241 throw new IllegalArgumentException("Device cannot be null");
242 }
243 // TODO Auto-generated method stub
244
245 }
246
247 private SwitchImpl getSwitchImpl(Switch sw) {
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800248 if (sw instanceof SwitchImpl) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800249 return (SwitchImpl) sw;
250 }
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800251 throw new ClassCastException("SwitchImpl expected, but found: " + sw);
252 }
253
254 private PortImpl getPortImpl(Port p) {
255 if (p instanceof PortImpl) {
256 return (PortImpl) p;
257 }
258 throw new ClassCastException("PortImpl expected, but found: " + p);
259 }
260
261 public boolean isSwitchInstanceInTopology(Switch sw) {
262 // check if the sw instance is valid in Topology
263 if (sw != switches.get(sw.getDpid())) {
264 return false;
265 }
266 return true;
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800267 }
268
269 public void loadWholeTopologyFromDB() {
270 // XXX clear everything first?
271
272 for (RCSwitch sw : RCSwitch.getAllSwitches()) {
273 try {
274 sw.read();
275 // TODO SwitchImpl probably should have a constructor from
276 // RCSwitch
Toshio Koide2f570c12014-02-06 16:55:32 -0800277 SwitchImpl memSw = new SwitchImpl(this, sw.getDpid());
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800278
279 addSwitch(memSw);
280 } catch (ObjectDoesntExistException e) {
281 log.error("Read Switch Failed, skipping", e);
282 }
283 }
284
285 for (RCPort p : RCPort.getAllPorts()) {
286 try {
287 p.read();
288
289 // TODO PortImpl probably should have a constructor from RCPort
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800290 Switch sw = this.getSwitch(p.getDpid());
291 if (sw == null) {
292 log.error("Switch {} missing when adding Port {}",
293 new Dpid(p.getDpid()), p);
294 continue;
295 }
Toshio Koide2f570c12014-02-06 16:55:32 -0800296 PortImpl memPort = new PortImpl(this, sw, p.getNumber());
Yuta HIGUCHI765cd0d2014-02-06 12:46:41 -0800297
298 addPort(memPort);
299 } catch (ObjectDoesntExistException e) {
300 log.error("Read Port Failed, skipping", e);
301 }
302 }
303
304 // TODO Is Device going to be in DB? If so, read from DB.
305 // for (RCDevice d : RCDevice.getAllDevices()) {
306 // try {
307 // d.read();
308 //
309 // } catch (ObjectDoesntExistException e) {
310 // log.debug("Read Device Failed, skipping", e);
311 // }
312 // }
313
314 for (RCLink l : RCLink.getAllLinks()) {
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800315 try {
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800316 l.read();
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800317
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800318 Switch srcSw = this.getSwitch(l.getSrc().dpid);
319 if (srcSw == null) {
320 log.error("Switch {} missing when adding Link {}",
321 new Dpid(l.getSrc().dpid), l);
322 continue;
323 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800324
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800325 Switch dstSw = this.getSwitch(l.getDst().dpid);
326 if (dstSw == null) {
327 log.error("Switch {} missing when adding Link {}",
328 new Dpid(l.getDst().dpid), l);
329 continue;
330 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800331
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800332 LinkImpl memLink = new LinkImpl(this,
333 srcSw.getPort(l.getSrc().number), dstSw.getPort(l
334 .getDst().number));
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800335
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800336 addLink(memLink);
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800337 } catch (ObjectDoesntExistException e) {
Yuta HIGUCHI4bfdd532014-02-07 13:47:36 -0800338 log.debug("Delete Link Failed", e);
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800339 }
Jonathan Hart062a2e82014-02-03 09:41:57 -0800340 }
Yuta HIGUCHI80829d12014-02-05 20:16:56 -0800341 }
Jonathan Hart062a2e82014-02-03 09:41:57 -0800342}