blob: b1f421312575d0b3e13a4fee969c8613fcc70f44 [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;
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080039
40
Jonathan Hart062a2e82014-02-03 09:41:57 -080041 public void addSwitch(Switch sw) {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080042
43 ArrayList<WriteOp> groupOp = new ArrayList<>();
44
Jonathan Hart062a2e82014-02-03 09:41:57 -080045 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
46 rcSwitch.setStatus(RCSwitch.STATUS.ACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080047
48 // XXX Is ForceCreating Switch on DB OK here?
49 // If ForceCreating, who ever is calling this method needs
50 // to assure that DPID is unique cluster-wide, etc.
51 groupOp.add(WriteOp.ForceCreate(rcSwitch));
52
Jonathan Hart062a2e82014-02-03 09:41:57 -080053 for (Port port : sw.getPorts()) {
54 RCPort rcPort = new RCPort(sw.getDpid(), (long)port.getNumber());
55 rcPort.setStatus(RCPort.STATUS.ACTIVE);
56 rcSwitch.addPortId(rcPort.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080057
58 groupOp.add(WriteOp.ForceCreate(rcPort));
Jonathan Hart062a2e82014-02-03 09:41:57 -080059 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080060
61 boolean failed = RCObject.multiWrite( groupOp );
62
63 if ( failed ) {
64 log.error("Adding Switch {} and it's ports failed.", sw.getDpid());
65 for ( WriteOp op : groupOp ) {
66 log.debug("Operation:{} for {} - Result:{}", op.getOp(), op.getObject(), op.getStatus() );
67
68 // If we changed the operation from ForceCreate to
69 // Conditional operation (Create/Update) then we should retry here.
70 }
71 }
72
Jonathan Hart062a2e82014-02-03 09:41:57 -080073 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080074
Jonathan Hart062a2e82014-02-03 09:41:57 -080075 public void deactivateSwitch(Switch sw) {
76 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080077
Jonathan Hart062a2e82014-02-03 09:41:57 -080078 List<RCObject> objectsToDeactive = new ArrayList<RCObject>();
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080079
Jonathan Hart062a2e82014-02-03 09:41:57 -080080 for (int i = 0; i < NUM_RETRIES; i++) {
81 try {
82 rcSwitch.read();
83 rcSwitch.setStatus(RCSwitch.STATUS.INACTIVE);
84 objectsToDeactive.add(rcSwitch);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080085
Jonathan Hart062a2e82014-02-03 09:41:57 -080086 for (Port p : sw.getPorts()) {
87 RCPort rcPort = new RCPort(sw.getDpid(), (long)p.getNumber());
88 rcPort.read();
89 rcPort.setStatus(RCPort.STATUS.INACTIVE);
90 objectsToDeactive.add(rcPort);
91 }
92 } catch (ObjectDoesntExistException e) {
93 log.warn("Trying to deactivate an object that doesn't exist", e);
94 // We don't care to much if the object wasn't there, it's
95 // being deactivated anyway
96 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080097
Jonathan Hart062a2e82014-02-03 09:41:57 -080098 try {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -080099 for (RCObject rcObject : objectsToDeactive) {
Jonathan Hart062a2e82014-02-03 09:41:57 -0800100 rcObject.update();
101 }
102 break;
103 } catch (ObjectDoesntExistException e) {
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800104 // Unlikely, and we don't care anyway.
Jonathan Hart062a2e82014-02-03 09:41:57 -0800105 // TODO But, this will cause everything else to fail
106 log.warn("Trying to deactivate object that doesn't exist", e);
107 } catch (WrongVersionException e) {
108 // Need to re-read and retry
109 }
110 }
111 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800112
Jonathan Hart062a2e82014-02-03 09:41:57 -0800113 public void addPort(Switch sw, Port port) {
114 RCSwitch rcSwitch = new RCSwitch(sw.getDpid());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800115
Jonathan Hart062a2e82014-02-03 09:41:57 -0800116 try {
117 rcSwitch.read();
118 } catch (ObjectDoesntExistException e) {
119 log.warn("Add port failed because switch {} doesn't exist", sw.getDpid(), e);
120 return;
121 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800122
Jonathan Hart062a2e82014-02-03 09:41:57 -0800123 RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
124 rcPort.setStatus(RCPort.STATUS.ACTIVE);
125 rcSwitch.addPortId(rcPort.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800126
Jonathan Hart062a2e82014-02-03 09:41:57 -0800127 writeObject(rcPort);
128 writeObject(rcSwitch);
129 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800130
Jonathan Hart062a2e82014-02-03 09:41:57 -0800131 public void deactivatePort(Port port) {
132 RCPort rcPort = new RCPort(port.getSwitch().getDpid(), (long)port.getNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800133
Jonathan Hart062a2e82014-02-03 09:41:57 -0800134 for (int i = 0; i < NUM_RETRIES; i++) {
135 try {
136 rcPort.read();
137 } catch (ObjectDoesntExistException e) {
138 // oh well, we were deactivating anyway
139 log.warn("Trying to deactivate a port that doesn't exist: {}", port);
140 return;
141 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800142
Jonathan Hart062a2e82014-02-03 09:41:57 -0800143 rcPort.setStatus(RCPort.STATUS.INACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800144
Jonathan Hart062a2e82014-02-03 09:41:57 -0800145 try {
146 rcPort.update();
147 break;
148 } catch (ObjectDoesntExistException | WrongVersionException e) {
149 // retry
150 }
151 }
152 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800153
Jonathan Hart062a2e82014-02-03 09:41:57 -0800154 public void addLink(Link link) {
155 RCLink rcLink = new RCLink(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber(),
156 link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800157
Jonathan Hart062a2e82014-02-03 09:41:57 -0800158 RCPort rcSrcPort = new RCPort(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber());
159 RCPort rcDstPort = new RCPort(link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800160
Jonathan Hart062a2e82014-02-03 09:41:57 -0800161 for (int i = 0; i < NUM_RETRIES; i++) {
162 try {
163 rcSrcPort.read();
164 rcDstPort.read();
165 rcLink.create();
166 } catch (ObjectDoesntExistException e) {
167 // port doesn't exist
168 log.error("Add link failed {}", link, e);
169 return;
170 } catch (ObjectExistsException e) {
171 log.debug("Link already exists {}", link);
172 return;
173 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800174
Jonathan Hart062a2e82014-02-03 09:41:57 -0800175 rcSrcPort.addLinkId(rcLink.getId());
176 rcDstPort.addLinkId(rcLink.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800177
Jonathan Hart062a2e82014-02-03 09:41:57 -0800178 rcLink.setStatus(RCLink.STATUS.ACTIVE);
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800179
Jonathan Hart062a2e82014-02-03 09:41:57 -0800180 try {
181 rcLink.update();
182 rcSrcPort.update();
183 rcDstPort.update();
184 break;
185 } catch (ObjectDoesntExistException | WrongVersionException e) {
186 log.debug(" ", e);
187 // retry
188 }
189 }
190 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800191
Jonathan Hart062a2e82014-02-03 09:41:57 -0800192 public void removeLink(Link link) {
193 RCLink rcLink = new RCLink(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber(),
194 link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800195
Jonathan Hart062a2e82014-02-03 09:41:57 -0800196 RCPort rcSrcPort = new RCPort(link.getSourceSwitchDpid(), (long)link.getSourcePortNumber());
197 RCPort rcDstPort = new RCPort(link.getDestinationSwitchDpid(), (long)link.getDestinationPortNumber());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800198
Jonathan Hart062a2e82014-02-03 09:41:57 -0800199 for (int i = 0; i < NUM_RETRIES; i++) {
200 try {
201 rcSrcPort.read();
202 rcDstPort.read();
203 rcLink.read();
204 } catch (ObjectDoesntExistException e) {
205 log.error("Remove link failed {}", link, e);
206 return;
207 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800208
Jonathan Hart062a2e82014-02-03 09:41:57 -0800209 rcSrcPort.removeLinkId(rcLink.getId());
210 rcDstPort.removeLinkId(rcLink.getId());
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800211
Jonathan Hart062a2e82014-02-03 09:41:57 -0800212 try {
213 rcSrcPort.update();
214 rcDstPort.update();
215 rcLink.delete();
216 } catch (ObjectDoesntExistException e) {
217 log.error("Remove link failed {}", link, e);
218 return;
219 } catch (WrongVersionException e) {
220 // retry
221 }
222 }
223 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800224
Jonathan Hart062a2e82014-02-03 09:41:57 -0800225 public void updateDevice(Device device) {
226 // TODO implement
227 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800228
Jonathan Hart062a2e82014-02-03 09:41:57 -0800229 public void removeDevice(Device device) {
230 // TODO implement
231 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800232
Jonathan Hart062a2e82014-02-03 09:41:57 -0800233 // TODO what happens if this fails? why could it fail?
234 private void writeObject(RCObject object) {
235 for (int i = 0; i < NUM_RETRIES; i++) {
236 try {
237 object.create();
238 } catch (ObjectExistsException e) {
239 try {
240 object.read();
241 } catch (ObjectDoesntExistException e1) {
242 // TODO Auto-generated catch block
243 log.error(" ", e);
244 return;
245 }
246 }
Yuta HIGUCHIb4335ad2014-02-05 09:56:07 -0800247
Jonathan Hart062a2e82014-02-03 09:41:57 -0800248 try {
249 // TODO check API for writing without caring what's there
250 object.update();
251 break;
252 } catch (ObjectDoesntExistException | WrongVersionException e) {
253 log.debug(" ", e);
254 // re-read and retry
255 }
256 }
257 }
258}