blob: b38c05742d0a56242edfa72cf1082eb1c34e4c73 [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 *
25 */
26public class SouthboundNetworkGraph {
27 private static final Logger log = LoggerFactory.getLogger(SouthboundNetworkGraph.class);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080028
Jonathan Hart062a2e82014-02-03 09:41:57 -080029 private static final int NUM_RETRIES = 10;
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080030
31
Jonathan Hart062a2e82014-02-03 09:41:57 -080032 public void addSwitch(Switch sw) {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080033
34 ArrayList<WriteOp> groupOp = new ArrayList<>();
35
Jonathan Hart062a2e82014-02-03 09:41:57 -080036 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
37 rcSwitch.setStatus(RCSwitch.STATUS.ACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080038
39 // XXX Is ForceCreating Switch on DB OK here?
40 // If ForceCreating, who ever is calling this method needs
41 // to assure that DPID is unique cluster-wide, etc.
42 groupOp.add(WriteOp.ForceCreate(rcSwitch));
43
Jonathan Hart062a2e82014-02-03 09:41:57 -080044 for (Port port : sw.getPorts()) {
45 RCPort rcPort = new RCPort(sw.getDpid(), (long)port.getNumber());
46 rcPort.setStatus(RCPort.STATUS.ACTIVE);
47 rcSwitch.addPortId(rcPort.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080048
49 groupOp.add(WriteOp.ForceCreate(rcPort));
Jonathan Hart062a2e82014-02-03 09:41:57 -080050 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080051
52 boolean failed = RCObject.multiWrite( groupOp );
53
54 if ( failed ) {
55 log.error("Adding Switch {} and it's ports failed.", sw.getDpid());
56 for ( WriteOp op : groupOp ) {
57 log.debug("Operation:{} for {} - Result:{}", op.getOp(), op.getObject(), op.getStatus() );
58
59 // If we changed the operation from ForceCreate to
60 // Conditional operation (Create/Update) then we should retry here.
61 }
62 }
63
Jonathan Hart062a2e82014-02-03 09:41:57 -080064 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080065
Jonathan Hart062a2e82014-02-03 09:41:57 -080066 public void deactivateSwitch(Switch sw) {
67 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080068
Jonathan Hart062a2e82014-02-03 09:41:57 -080069 List<RCObject> objectsToDeactive = new ArrayList<RCObject>();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080070
Jonathan Hart062a2e82014-02-03 09:41:57 -080071 for (int i = 0; i < NUM_RETRIES; i++) {
72 try {
73 rcSwitch.read();
74 rcSwitch.setStatus(RCSwitch.STATUS.INACTIVE);
75 objectsToDeactive.add(rcSwitch);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080076
Jonathan Hart062a2e82014-02-03 09:41:57 -080077 for (Port p : sw.getPorts()) {
78 RCPort rcPort = new RCPort(sw.getDpid(), (long)p.getNumber());
79 rcPort.read();
80 rcPort.setStatus(RCPort.STATUS.INACTIVE);
81 objectsToDeactive.add(rcPort);
82 }
83 } catch (ObjectDoesntExistException e) {
84 log.warn("Trying to deactivate an object that doesn't exist", e);
85 // We don't care to much if the object wasn't there, it's
86 // being deactivated anyway
87 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080088
Jonathan Hart062a2e82014-02-03 09:41:57 -080089 try {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080090 for (RCObject rcObject : objectsToDeactive) {
Jonathan Hart062a2e82014-02-03 09:41:57 -080091 rcObject.update();
92 }
93 break;
94 } catch (ObjectDoesntExistException e) {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080095 // Unlikely, and we don't care anyway.
Jonathan Hart062a2e82014-02-03 09:41:57 -080096 // TODO But, this will cause everything else to fail
97 log.warn("Trying to deactivate object that doesn't exist", e);
98 } catch (WrongVersionException e) {
99 // Need to re-read and retry
100 }
101 }
102 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800103
Jonathan Hart062a2e82014-02-03 09:41:57 -0800104 public void addPort(Switch sw, Port port) {
105 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800106
Jonathan Hart062a2e82014-02-03 09:41:57 -0800107 try {
108 rcSwitch.read();
109 } catch (ObjectDoesntExistException e) {
110 log.warn("Add port failed because switch {} doesn't exist", sw.getDpid(), e);
111 return;
112 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800113
Jonathan Hart062a2e82014-02-03 09:41:57 -0800114 RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
115 rcPort.setStatus(RCPort.STATUS.ACTIVE);
116 rcSwitch.addPortId(rcPort.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800117
Jonathan Hart062a2e82014-02-03 09:41:57 -0800118 writeObject(rcPort);
119 writeObject(rcSwitch);
120 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800121
Jonathan Hart062a2e82014-02-03 09:41:57 -0800122 public void deactivatePort(Port port) {
123 RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800124
Jonathan Hart062a2e82014-02-03 09:41:57 -0800125 for (int i = 0; i < NUM_RETRIES; i++) {
126 try {
127 rcPort.read();
128 } catch (ObjectDoesntExistException e) {
129 // oh well, we were deactivating anyway
130 log.warn("Trying to deactivate a port that doesn't exist: {}", port);
131 return;
132 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800133
Jonathan Hart062a2e82014-02-03 09:41:57 -0800134 rcPort.setStatus(RCPort.STATUS.INACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800135
Jonathan Hart062a2e82014-02-03 09:41:57 -0800136 try {
137 rcPort.update();
138 break;
139 } catch (ObjectDoesntExistException | WrongVersionException e) {
140 // retry
141 }
142 }
143 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800144
Jonathan Hart062a2e82014-02-03 09:41:57 -0800145 public void addLink(Link link) {
146 RCLink rcLink = new RCLink(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber(),
147 link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800148
Jonathan Hart062a2e82014-02-03 09:41:57 -0800149 RCPort rcSrcPort = new RCPort(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber());
150 RCPort rcDstPort = new RCPort(link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800151
Jonathan Hart062a2e82014-02-03 09:41:57 -0800152 for (int i = 0; i < NUM_RETRIES; i++) {
153 try {
154 rcSrcPort.read();
155 rcDstPort.read();
156 rcLink.create();
157 } catch (ObjectDoesntExistException e) {
158 // port doesn't exist
159 log.error("Add link failed {}", link, e);
160 return;
161 } catch (ObjectExistsException e) {
162 log.debug("Link already exists {}", link);
163 return;
164 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800165
Jonathan Hart062a2e82014-02-03 09:41:57 -0800166 rcSrcPort.addLinkId(rcLink.getId());
167 rcDstPort.addLinkId(rcLink.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800168
Jonathan Hart062a2e82014-02-03 09:41:57 -0800169 rcLink.setStatus(RCLink.STATUS.ACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800170
Jonathan Hart062a2e82014-02-03 09:41:57 -0800171 try {
172 rcLink.update();
173 rcSrcPort.update();
174 rcDstPort.update();
175 break;
176 } catch (ObjectDoesntExistException | WrongVersionException e) {
177 log.debug(" ", e);
178 // retry
179 }
180 }
181 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800182
Jonathan Hart062a2e82014-02-03 09:41:57 -0800183 public void removeLink(Link link) {
184 RCLink rcLink = new RCLink(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber(),
185 link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800186
Jonathan Hart062a2e82014-02-03 09:41:57 -0800187 RCPort rcSrcPort = new RCPort(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber());
188 RCPort rcDstPort = new RCPort(link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800189
Jonathan Hart062a2e82014-02-03 09:41:57 -0800190 for (int i = 0; i < NUM_RETRIES; i++) {
191 try {
192 rcSrcPort.read();
193 rcDstPort.read();
194 rcLink.read();
195 } catch (ObjectDoesntExistException e) {
196 log.error("Remove link failed {}", link, e);
197 return;
198 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800199
Jonathan Hart062a2e82014-02-03 09:41:57 -0800200 rcSrcPort.removeLinkId(rcLink.getId());
201 rcDstPort.removeLinkId(rcLink.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800202
Jonathan Hart062a2e82014-02-03 09:41:57 -0800203 try {
204 rcSrcPort.update();
205 rcDstPort.update();
206 rcLink.delete();
207 } catch (ObjectDoesntExistException e) {
208 log.error("Remove link failed {}", link, e);
209 return;
210 } catch (WrongVersionException e) {
211 // retry
212 }
213 }
214 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800215
Jonathan Hart062a2e82014-02-03 09:41:57 -0800216 public void updateDevice(Device device) {
217 // TODO implement
218 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800219
Jonathan Hart062a2e82014-02-03 09:41:57 -0800220 public void removeDevice(Device device) {
221 // TODO implement
222 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800223
Jonathan Hart062a2e82014-02-03 09:41:57 -0800224 // TODO what happens if this fails? why could it fail?
225 private void writeObject(RCObject object) {
226 for (int i = 0; i < NUM_RETRIES; i++) {
227 try {
228 object.create();
229 } catch (ObjectExistsException e) {
230 try {
231 object.read();
232 } catch (ObjectDoesntExistException e1) {
233 // TODO Auto-generated catch block
234 log.error(" ", e);
235 return;
236 }
237 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800238
Jonathan Hart062a2e82014-02-03 09:41:57 -0800239 try {
240 // TODO check API for writing without caring what's there
241 object.update();
242 break;
243 } catch (ObjectDoesntExistException | WrongVersionException e) {
244 log.debug(" ", e);
245 // re-read and retry
246 }
247 }
248 }
249}