blob: cb52d1542c71bff2d4472674bf8b62dd0d3c56a2 [file] [log] [blame]
Jonathan Hart062a2e82014-02-03 09:41:57 -08001package net.onrc.onos.ofcontroller.networkgraph;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import net.onrc.onos.datastore.RCObject;
7import net.onrc.onos.datastore.topology.RCLink;
8import net.onrc.onos.datastore.topology.RCPort;
9import net.onrc.onos.datastore.topology.RCSwitch;
10
11import org.slf4j.Logger;
12import org.slf4j.LoggerFactory;
13
14import edu.stanford.ramcloud.JRamCloud.ObjectDoesntExistException;
15import edu.stanford.ramcloud.JRamCloud.ObjectExistsException;
16import edu.stanford.ramcloud.JRamCloud.WrongVersionException;
17
18/**
19 * The southbound interface to the network graph which allows clients to
20 * mutate the graph. This class will maintain the invariants of the network
21 * graph. The southbound discovery modules will use this interface to update
22 * the network graph as they learn about the state of the network.
23 *
24 */
25public class SouthboundNetworkGraph {
26 private static final Logger log = LoggerFactory.getLogger(SouthboundNetworkGraph.class);
27
28 private static final int NUM_RETRIES = 10;
29
30
31 public void addSwitch(Switch sw) {
32 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
33 rcSwitch.setStatus(RCSwitch.STATUS.ACTIVE);
34
35 for (Port port : sw.getPorts()) {
36 RCPort rcPort = new RCPort(sw.getDpid(), (long)port.getNumber());
37 rcPort.setStatus(RCPort.STATUS.ACTIVE);
38 rcSwitch.addPortId(rcPort.getId());
39
40 // TODO check how to write switch+ports together
41 writeObject(rcPort);
42 }
43
44 writeObject(rcSwitch);
45 }
46
47 public void deactivateSwitch(Switch sw) {
48 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
49
50 List<RCObject> objectsToDeactive = new ArrayList<RCObject>();
51
52 for (int i = 0; i < NUM_RETRIES; i++) {
53 try {
54 rcSwitch.read();
55 rcSwitch.setStatus(RCSwitch.STATUS.INACTIVE);
56 objectsToDeactive.add(rcSwitch);
57
58 for (Port p : sw.getPorts()) {
59 RCPort rcPort = new RCPort(sw.getDpid(), (long)p.getNumber());
60 rcPort.read();
61 rcPort.setStatus(RCPort.STATUS.INACTIVE);
62 objectsToDeactive.add(rcPort);
63 }
64 } catch (ObjectDoesntExistException e) {
65 log.warn("Trying to deactivate an object that doesn't exist", e);
66 // We don't care to much if the object wasn't there, it's
67 // being deactivated anyway
68 }
69
70 try {
71 for (RCObject rcObject : objectsToDeactive) {
72 rcObject.update();
73 }
74 break;
75 } catch (ObjectDoesntExistException e) {
76 // Unlikely, and we don't care anyway.
77 // TODO But, this will cause everything else to fail
78 log.warn("Trying to deactivate object that doesn't exist", e);
79 } catch (WrongVersionException e) {
80 // Need to re-read and retry
81 }
82 }
83 }
84
85 public void addPort(Switch sw, Port port) {
86 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
87
88 try {
89 rcSwitch.read();
90 } catch (ObjectDoesntExistException e) {
91 log.warn("Add port failed because switch {} doesn't exist", sw.getDpid(), e);
92 return;
93 }
94
95 RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
96 rcPort.setStatus(RCPort.STATUS.ACTIVE);
97 rcSwitch.addPortId(rcPort.getId());
98
99 writeObject(rcPort);
100 writeObject(rcSwitch);
101 }
102
103 public void deactivatePort(Port port) {
104 RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
105
106 for (int i = 0; i < NUM_RETRIES; i++) {
107 try {
108 rcPort.read();
109 } catch (ObjectDoesntExistException e) {
110 // oh well, we were deactivating anyway
111 log.warn("Trying to deactivate a port that doesn't exist: {}", port);
112 return;
113 }
114
115 rcPort.setStatus(RCPort.STATUS.INACTIVE);
116
117 try {
118 rcPort.update();
119 break;
120 } catch (ObjectDoesntExistException | WrongVersionException e) {
121 // retry
122 }
123 }
124 }
125
126 public void addLink(Link link) {
127 RCLink rcLink = new RCLink(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber(),
128 link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
129
130 RCPort rcSrcPort = new RCPort(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber());
131 RCPort rcDstPort = new RCPort(link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
132
133 for (int i = 0; i < NUM_RETRIES; i++) {
134 try {
135 rcSrcPort.read();
136 rcDstPort.read();
137 rcLink.create();
138 } catch (ObjectDoesntExistException e) {
139 // port doesn't exist
140 log.error("Add link failed {}", link, e);
141 return;
142 } catch (ObjectExistsException e) {
143 log.debug("Link already exists {}", link);
144 return;
145 }
146
147 rcSrcPort.addLinkId(rcLink.getId());
148 rcDstPort.addLinkId(rcLink.getId());
149
150 rcLink.setStatus(RCLink.STATUS.ACTIVE);
151
152 try {
153 rcLink.update();
154 rcSrcPort.update();
155 rcDstPort.update();
156 break;
157 } catch (ObjectDoesntExistException | WrongVersionException e) {
158 log.debug(" ", e);
159 // retry
160 }
161 }
162 }
163
164 public void removeLink(Link link) {
165 RCLink rcLink = new RCLink(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber(),
166 link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
167
168 RCPort rcSrcPort = new RCPort(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber());
169 RCPort rcDstPort = new RCPort(link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
170
171 for (int i = 0; i < NUM_RETRIES; i++) {
172 try {
173 rcSrcPort.read();
174 rcDstPort.read();
175 rcLink.read();
176 } catch (ObjectDoesntExistException e) {
177 log.error("Remove link failed {}", link, e);
178 return;
179 }
180
181 rcSrcPort.removeLinkId(rcLink.getId());
182 rcDstPort.removeLinkId(rcLink.getId());
183
184 try {
185 rcSrcPort.update();
186 rcDstPort.update();
187 rcLink.delete();
188 } catch (ObjectDoesntExistException e) {
189 log.error("Remove link failed {}", link, e);
190 return;
191 } catch (WrongVersionException e) {
192 // retry
193 }
194 }
195 }
196
197 public void updateDevice(Device device) {
198 // TODO implement
199 }
200
201 public void removeDevice(Device device) {
202 // TODO implement
203 }
204
205 // TODO what happens if this fails? why could it fail?
206 private void writeObject(RCObject object) {
207 for (int i = 0; i < NUM_RETRIES; i++) {
208 try {
209 object.create();
210 } catch (ObjectExistsException e) {
211 try {
212 object.read();
213 } catch (ObjectDoesntExistException e1) {
214 // TODO Auto-generated catch block
215 log.error(" ", e);
216 return;
217 }
218 }
219
220 try {
221 // TODO check API for writing without caring what's there
222 object.update();
223 break;
224 } catch (ObjectDoesntExistException | WrongVersionException e) {
225 log.debug(" ", e);
226 // re-read and retry
227 }
228 }
229 }
230}