blob: e9de66566272efe53ace440c4882af43d70d8b81 [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;
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -08007import net.onrc.onos.datastore.RCObject.WriteOp;
Jonathan Hart062a2e82014-02-03 09:41:57 -08008import net.onrc.onos.datastore.topology.RCLink;
9import net.onrc.onos.datastore.topology.RCPort;
10import net.onrc.onos.datastore.topology.RCSwitch;
11
12import org.slf4j.Logger;
13import org.slf4j.LoggerFactory;
14
15import edu.stanford.ramcloud.JRamCloud.ObjectDoesntExistException;
16import edu.stanford.ramcloud.JRamCloud.ObjectExistsException;
17import edu.stanford.ramcloud.JRamCloud.WrongVersionException;
18
19/**
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080020 * The southbound interface to the network graph which allows clients to
Jonathan Hart062a2e82014-02-03 09:41:57 -080021 * mutate the graph. This class will maintain the invariants of the network
22 * graph. The southbound discovery modules will use this interface to update
23 * the network graph as they learn about the state of the network.
24 *
Yuta HIGUCHI181d34d2014-02-05 15:05:46 -080025 * Modification to the Network Map by this module will:
26 * 1. Writes to Cluster-wide DataStore.
27 * 2. Update ONOS instance In-memory Network Map.
28 * 3. Send-out Notification. (TBD)
29 * (XXX: To update other instances In-memory Network Map,
30 * notification should be triggered here.
31 * But if we want to aggregate notification to minimize notification,
32 * It might be better for the caller to trigger notification.)
33 *
Jonathan Hart062a2e82014-02-03 09:41:57 -080034 */
35public class SouthboundNetworkGraph {
36 private static final Logger log = LoggerFactory.getLogger(SouthboundNetworkGraph.class);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080037
Jonathan Hart062a2e82014-02-03 09:41:57 -080038 private static final int NUM_RETRIES = 10;
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080039
40 private final NetworkGraphImpl graph;
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080041
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080042 public SouthboundNetworkGraph(NetworkGraphImpl graph) {
43 this.graph = graph;
44 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080045
Jonathan Hart062a2e82014-02-03 09:41:57 -080046 public void addSwitch(Switch sw) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080047 log.debug("Adding switch {}", sw);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080048 ArrayList<WriteOp> groupOp = new ArrayList<>();
49
Jonathan Hart062a2e82014-02-03 09:41:57 -080050 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
51 rcSwitch.setStatus(RCSwitch.STATUS.ACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080052
53 // XXX Is ForceCreating Switch on DB OK here?
54 // If ForceCreating, who ever is calling this method needs
55 // to assure that DPID is unique cluster-wide, etc.
56 groupOp.add(WriteOp.ForceCreate(rcSwitch));
57
Jonathan Hart062a2e82014-02-03 09:41:57 -080058 for (Port port : sw.getPorts()) {
59 RCPort rcPort = new RCPort(sw.getDpid(), (long)port.getNumber());
60 rcPort.setStatus(RCPort.STATUS.ACTIVE);
61 rcSwitch.addPortId(rcPort.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080062
63 groupOp.add(WriteOp.ForceCreate(rcPort));
Jonathan Hart062a2e82014-02-03 09:41:57 -080064 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080065
66 boolean failed = RCObject.multiWrite( groupOp );
67
68 if ( failed ) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080069 log.error("Adding Switch {} and its ports failed.", sw.getDpid());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080070 for ( WriteOp op : groupOp ) {
71 log.debug("Operation:{} for {} - Result:{}", op.getOp(), op.getObject(), op.getStatus() );
72
73 // If we changed the operation from ForceCreate to
74 // Conditional operation (Create/Update) then we should retry here.
75 }
76 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080077 else {
78 // Publish event to the in-memory cache
79 graph.addSwitch(sw);
80 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080081
Jonathan Hart062a2e82014-02-03 09:41:57 -080082 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080083
Jonathan Hart062a2e82014-02-03 09:41:57 -080084 public void deactivateSwitch(Switch sw) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -080085 log.debug("Deactivating switch {}", sw);
Jonathan Hart062a2e82014-02-03 09:41:57 -080086 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080087
Jonathan Hart062a2e82014-02-03 09:41:57 -080088 List<RCObject> objectsToDeactive = new ArrayList<RCObject>();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080089
Jonathan Hart062a2e82014-02-03 09:41:57 -080090 for (int i = 0; i < NUM_RETRIES; i++) {
91 try {
92 rcSwitch.read();
93 rcSwitch.setStatus(RCSwitch.STATUS.INACTIVE);
94 objectsToDeactive.add(rcSwitch);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080095
Jonathan Hart062a2e82014-02-03 09:41:57 -080096 for (Port p : sw.getPorts()) {
97 RCPort rcPort = new RCPort(sw.getDpid(), (long)p.getNumber());
98 rcPort.read();
99 rcPort.setStatus(RCPort.STATUS.INACTIVE);
100 objectsToDeactive.add(rcPort);
101 }
102 } catch (ObjectDoesntExistException e) {
103 log.warn("Trying to deactivate an object that doesn't exist", e);
104 // We don't care to much if the object wasn't there, it's
105 // being deactivated anyway
106 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800107
Jonathan Hart062a2e82014-02-03 09:41:57 -0800108 try {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800109 for (RCObject rcObject : objectsToDeactive) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800110 rcObject.update();
111 }
112 break;
113 } catch (ObjectDoesntExistException e) {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800114 // Unlikely, and we don't care anyway.
Jonathan Hart062a2e82014-02-03 09:41:57 -0800115 // TODO But, this will cause everything else to fail
116 log.warn("Trying to deactivate object that doesn't exist", e);
117 } catch (WrongVersionException e) {
118 // Need to re-read and retry
119 }
120 }
121 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800122
Jonathan Hart062a2e82014-02-03 09:41:57 -0800123 public void addPort(Switch sw, Port port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800124 log.debug("Adding port {}", port);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800125 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800126
Jonathan Hart062a2e82014-02-03 09:41:57 -0800127 try {
128 rcSwitch.read();
129 } catch (ObjectDoesntExistException e) {
130 log.warn("Add port failed because switch {} doesn't exist", sw.getDpid(), e);
131 return;
132 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800133
Jonathan Hart062a2e82014-02-03 09:41:57 -0800134 RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
135 rcPort.setStatus(RCPort.STATUS.ACTIVE);
136 rcSwitch.addPortId(rcPort.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800137
Jonathan Hart062a2e82014-02-03 09:41:57 -0800138 writeObject(rcPort);
139 writeObject(rcSwitch);
140 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800141
Jonathan Hart062a2e82014-02-03 09:41:57 -0800142 public void deactivatePort(Port port) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800143 log.debug("Deactivating port {}", port);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800144 RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800145
Jonathan Hart062a2e82014-02-03 09:41:57 -0800146 for (int i = 0; i < NUM_RETRIES; i++) {
147 try {
148 rcPort.read();
149 } catch (ObjectDoesntExistException e) {
150 // oh well, we were deactivating anyway
151 log.warn("Trying to deactivate a port that doesn't exist: {}", port);
152 return;
153 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800154
Jonathan Hart062a2e82014-02-03 09:41:57 -0800155 rcPort.setStatus(RCPort.STATUS.INACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800156
Jonathan Hart062a2e82014-02-03 09:41:57 -0800157 try {
158 rcPort.update();
159 break;
160 } catch (ObjectDoesntExistException | WrongVersionException e) {
161 // retry
162 }
163 }
164 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800165
Jonathan Hart062a2e82014-02-03 09:41:57 -0800166 public void addLink(Link link) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800167 log.debug("Adding link {}", link);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800168 RCLink rcLink = new RCLink(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber(),
169 link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800170
Jonathan Hart062a2e82014-02-03 09:41:57 -0800171 RCPort rcSrcPort = new RCPort(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber());
172 RCPort rcDstPort = new RCPort(link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800173
Jonathan Hart062a2e82014-02-03 09:41:57 -0800174 for (int i = 0; i < NUM_RETRIES; i++) {
175 try {
176 rcSrcPort.read();
177 rcDstPort.read();
178 rcLink.create();
179 } catch (ObjectDoesntExistException e) {
180 // port doesn't exist
181 log.error("Add link failed {}", link, e);
182 return;
183 } catch (ObjectExistsException e) {
184 log.debug("Link already exists {}", link);
185 return;
186 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800187
Jonathan Hart062a2e82014-02-03 09:41:57 -0800188 rcSrcPort.addLinkId(rcLink.getId());
189 rcDstPort.addLinkId(rcLink.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800190
Jonathan Hart062a2e82014-02-03 09:41:57 -0800191 rcLink.setStatus(RCLink.STATUS.ACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800192
Jonathan Hart062a2e82014-02-03 09:41:57 -0800193 try {
194 rcLink.update();
195 rcSrcPort.update();
196 rcDstPort.update();
197 break;
198 } catch (ObjectDoesntExistException | WrongVersionException e) {
199 log.debug(" ", e);
200 // retry
201 }
202 }
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800203
204 // Publish event to in-memory cache
205 graph.addLink(link);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800206 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800207
Jonathan Hart062a2e82014-02-03 09:41:57 -0800208 public void removeLink(Link link) {
Jonathan Hart4b5bbb52014-02-06 10:09:31 -0800209 log.debug("Removing link {}", link);
Jonathan Hart062a2e82014-02-03 09:41:57 -0800210 RCLink rcLink = new RCLink(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber(),
211 link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800212
Jonathan Hart062a2e82014-02-03 09:41:57 -0800213 RCPort rcSrcPort = new RCPort(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber());
214 RCPort rcDstPort = new RCPort(link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800215
Jonathan Hart062a2e82014-02-03 09:41:57 -0800216 for (int i = 0; i < NUM_RETRIES; i++) {
217 try {
218 rcSrcPort.read();
219 rcDstPort.read();
220 rcLink.read();
221 } catch (ObjectDoesntExistException e) {
222 log.error("Remove link failed {}", link, e);
223 return;
224 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800225
Jonathan Hart062a2e82014-02-03 09:41:57 -0800226 rcSrcPort.removeLinkId(rcLink.getId());
227 rcDstPort.removeLinkId(rcLink.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800228
Jonathan Hart062a2e82014-02-03 09:41:57 -0800229 try {
230 rcSrcPort.update();
231 rcDstPort.update();
232 rcLink.delete();
233 } catch (ObjectDoesntExistException e) {
234 log.error("Remove link failed {}", link, e);
235 return;
236 } catch (WrongVersionException e) {
237 // retry
238 }
239 }
240 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800241
Jonathan Hart062a2e82014-02-03 09:41:57 -0800242 public void updateDevice(Device device) {
243 // TODO implement
244 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800245
Jonathan Hart062a2e82014-02-03 09:41:57 -0800246 public void removeDevice(Device device) {
247 // TODO implement
248 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800249
Jonathan Hart062a2e82014-02-03 09:41:57 -0800250 // TODO what happens if this fails? why could it fail?
251 private void writeObject(RCObject object) {
252 for (int i = 0; i < NUM_RETRIES; i++) {
253 try {
254 object.create();
255 } catch (ObjectExistsException e) {
256 try {
257 object.read();
258 } catch (ObjectDoesntExistException e1) {
259 // TODO Auto-generated catch block
260 log.error(" ", e);
261 return;
262 }
263 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800264
Jonathan Hart062a2e82014-02-03 09:41:57 -0800265 try {
266 // TODO check API for writing without caring what's there
267 object.update();
268 break;
269 } catch (ObjectDoesntExistException | WrongVersionException e) {
270 log.debug(" ", e);
271 // re-read and retry
272 }
273 }
274 }
275}