blob: 32f28be4765e59db166f565fc1f8a3869735c448 [file] [log] [blame]
Pankaj Berdefc30d3f2013-03-28 13:34:44 -07001package net.onrc.onos.flow;
2
3import java.util.ArrayList;
Pankaj Berde37f037f2013-04-03 11:52:11 -07004import java.util.Collections;
5import java.util.HashMap;
6import java.util.HashSet;
7import java.util.LinkedList;
Pankaj Berdefc30d3f2013-03-28 13:34:44 -07008import java.util.List;
9import java.util.Map;
Pankaj Berde37f037f2013-04-03 11:52:11 -070010import java.util.Queue;
11import java.util.Set;
12
13import org.openflow.util.HexString;
14import org.slf4j.Logger;
15import org.slf4j.LoggerFactory;
16
17import com.tinkerpop.blueprints.Direction;
18import com.tinkerpop.blueprints.Vertex;
Pankaj Berdefc30d3f2013-03-28 13:34:44 -070019
20import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
21import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
22import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
Pankaj Berde37f037f2013-04-03 11:52:11 -070023import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
Pankaj Berdefc30d3f2013-03-28 13:34:44 -070024import net.floodlightcontroller.core.IOFSwitch;
Pankaj Berde37f037f2013-04-03 11:52:11 -070025import net.floodlightcontroller.util.DataPath;
26import net.floodlightcontroller.util.Dpid;
Pankaj Berdefc30d3f2013-03-28 13:34:44 -070027import net.floodlightcontroller.util.FlowEntry;
Pankaj Berde37f037f2013-04-03 11:52:11 -070028import net.floodlightcontroller.util.FlowEntryAction;
29import net.floodlightcontroller.util.FlowEntryMatch;
Pankaj Berdefc30d3f2013-03-28 13:34:44 -070030import net.floodlightcontroller.util.FlowPath;
Pankaj Berde37f037f2013-04-03 11:52:11 -070031import net.floodlightcontroller.util.Port;
32import net.floodlightcontroller.util.SwitchPort;
33import net.onrc.onos.util.GraphDBConnection;
Toshio Koide57b99b52013-06-13 14:09:23 -070034import net.onrc.onos.util.GraphDBOperation;
Pankaj Berde37f037f2013-04-03 11:52:11 -070035import net.onrc.onos.util.LocalTopologyEventListener;
36import net.onrc.onos.util.GraphDBConnection.Transaction;
Pankaj Berdefc30d3f2013-03-28 13:34:44 -070037
38public class FlowManagerImpl implements IFlowManager {
Pankaj Berde37f037f2013-04-03 11:52:11 -070039
40 protected static Logger log = LoggerFactory.getLogger(LocalTopologyEventListener.class);
Toshio Koide57b99b52013-06-13 14:09:23 -070041 protected GraphDBOperation op;
Pankaj Berdefc30d3f2013-03-28 13:34:44 -070042
43 @Override
44 public void createFlow(IPortObject src_port, IPortObject dest_port) {
45 // TODO Auto-generated method stub
46
47 }
48
49 @Override
50 public Iterable<FlowPath> getFlows(IPortObject src_port,
51 IPortObject dest_port) {
52 // TODO Auto-generated method stub
53 return null;
54 }
55
56 @Override
57 public Iterable<FlowPath> getOutFlows(IPortObject port) {
58 // TODO Auto-generated method stub
59 List<FlowPath> flowPaths = new ArrayList<FlowPath> ();
60 Iterable<IFlowEntry> flowEntries = port.getOutFlowEntries();
61
62 for(IFlowEntry fe: flowEntries) {
Pankaj Berdeb4bdf702013-03-28 13:37:24 -070063 IFlowPath flow = fe.getFlow();
Pankaj Berdefc30d3f2013-03-28 13:34:44 -070064 FlowPath flowPath = new FlowPath(flow);
65 flowPaths.add(flowPath);
66 }
67 return flowPaths;
68 }
69
70 @Override
71 public void reconcileFlows(IPortObject src_port) {
72 // TODO Auto-generated method stub
73
Pankaj Berde37f037f2013-04-03 11:52:11 -070074 log.debug("Reconcile Flows for Port removed: {}:{}",src_port.getSwitch().getDPID(),src_port.getNumber());
Pankaj Berdefc30d3f2013-03-28 13:34:44 -070075 Iterable<IFlowEntry> flowEntries = src_port.getOutFlowEntries();
76
77 for(IFlowEntry fe: flowEntries) {
78 IFlowPath flow = fe.getFlow();
79 reconcileFlow(flow);
80 }
81 }
82
83 private void reconcileFlow(IFlowPath flow) {
84 // TODO Auto-generated method stub
Pankaj Berde37f037f2013-04-03 11:52:11 -070085 String src_dpid = flow.getSrcSwitch();
86 String dst_dpid = flow.getDstSwitch();
87 Short src_port = flow.getSrcPort();
88 Short dst_port = flow.getDstPort();
89 IPortObject src = null;
90 IPortObject dst = null;
Toshio Koide57b99b52013-06-13 14:09:23 -070091 src = op.searchPort(src_dpid, src_port);
92 dst = op.searchPort(dst_dpid, dst_port);
Pankaj Berde37f037f2013-04-03 11:52:11 -070093 if (src != null && dst != null) {
94 FlowPath newFlow = this.computeFlowPath(src,dst);
95 installFlow(newFlow);
96 removeFlow(flow);
97 }
98
99 }
100
101 private void removeFlow(IFlowPath flow) {
102 // TODO Auto-generated method stub
103
104 }
105
106 private void installFlow(FlowPath newFlow) {
107 // TODO Auto-generated method stub
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700108
109 }
110
111 @Override
112 public void reconcileFlow(IPortObject src_port, IPortObject dest_port) {
113 // TODO Auto-generated method stub
114
115 }
116
117 @Override
118 public FlowPath computeFlowPath(IPortObject src_port, IPortObject dest_port) {
119 // TODO Auto-generated method stub
Pankaj Berde37f037f2013-04-03 11:52:11 -0700120 DataPath dataPath = new DataPath();
121
122 // FIXME: Bad idea to use FloodLight data structures (SwitchPort)
123
124 dataPath.setSrcPort(new SwitchPort(new Dpid(src_port.getSwitch().getDPID()),
125 new Port(src_port.getNumber())));
126 dataPath.setDstPort(new SwitchPort(new Dpid(src_port.getSwitch().getDPID()),
127 new Port(src_port.getNumber())));
128
129 if (src_port.getSwitch().equals(dest_port.getSwitch())) {
130 // on same switch create quick path
131 FlowEntry flowEntry = new FlowEntry();
132 flowEntry.setDpid(new Dpid(src_port.getSwitch().getDPID()));
133 flowEntry.setInPort(new Port(src_port.getNumber()));
134 flowEntry.setOutPort(new Port(src_port.getNumber()));
135 flowEntry.setFlowEntryMatch(new FlowEntryMatch());
136 flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
137
138 // Set the outgoing port output action
139 ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
140 if (flowEntryActions == null) {
141 flowEntryActions = new ArrayList<FlowEntryAction>();
142 flowEntry.setFlowEntryActions(flowEntryActions);
143 }
144 FlowEntryAction flowEntryAction = new FlowEntryAction();
145 flowEntryAction.setActionOutput(flowEntry.outPort());
146 flowEntryActions.add(flowEntryAction);
147 dataPath.flowEntries().add(flowEntry);
148
149 FlowPath flowPath = new FlowPath();
150 flowPath.setDataPath(dataPath);
151
152 return flowPath;
153 }
154 Vertex v_src = src_port.getSwitch().asVertex();
155 Vertex v_dest = dest_port.getSwitch().asVertex();
156
157 //
158 // Implement the Shortest Path computation by using Breath First Search
159 //
160 Set<Vertex> visitedSet = new HashSet<Vertex>();
161 Queue<Vertex> processingList = new LinkedList<Vertex>();
162 Map<Vertex, Vertex> previousVertexMap = new HashMap<Vertex, Vertex>();
163
164 processingList.add(v_src);
165 visitedSet.add(v_src);
166 Boolean path_found = false;
167 while (! processingList.isEmpty()) {
168 Vertex nextVertex = processingList.poll();
169 if (v_dest.equals(nextVertex)) {
170 path_found = true;
171 break;
172 }
173 for (Vertex parentPort : nextVertex.getVertices(Direction.OUT, "on")) {
174 for (Vertex childPort : parentPort.getVertices(Direction.OUT, "link")) {
175 for (Vertex child : childPort.getVertices(Direction.IN, "on")) {
176 // Ignore inactive switches
177 String state = child.getProperty("state").toString();
178 if (! state.equals(SwitchState.ACTIVE.toString()))
179 continue;
180
181 if (! visitedSet.contains(child)) {
182 previousVertexMap.put(parentPort, nextVertex);
183 previousVertexMap.put(childPort, parentPort);
184 previousVertexMap.put(child, childPort);
185 visitedSet.add(child);
186 processingList.add(child);
187 }
188 }
189 }
190 }
191 }
192 if (! path_found) {
193 return null; // No path found
194 }
195
196 List<Vertex> resultPath = new LinkedList<Vertex>();
197 Vertex previousVertex = v_dest;
198 resultPath.add(v_dest);
199 while (! v_src.equals(previousVertex)) {
200 Vertex currentVertex = previousVertexMap.get(previousVertex);
201 resultPath.add(currentVertex);
202 previousVertex = currentVertex;
203 }
204 Collections.reverse(resultPath);
205
206 // Loop through the result and prepare the return result
207 // as a list of Flow Entries.
208 //
209 long nodeId = 0;
210 short portId = 0;
211 Port inPort = new Port(src_port.getNumber());
212 Port outPort = new Port();
213 int idx = 0;
214 for (Vertex v: resultPath) {
215 String type = v.getProperty("type").toString();
216 // System.out.println("type: " + type);
217 if (type.equals("port")) {
218 String number = v.getProperty("number").toString();
219 // System.out.println("number: " + number);
220
221 Object obj = v.getProperty("number");
222 // String class_str = obj.getClass().toString();
223 if (obj instanceof Short) {
224 portId = (Short)obj;
225 } else if (obj instanceof Integer) {
226 Integer int_nodeId = (Integer)obj;
227 portId = int_nodeId.shortValue();
228 // int int_nodeId = (Integer)obj;
229 // portId = (short)int_nodeId.;
230 }
231 } else if (type.equals("switch")) {
232 String dpid = v.getProperty("dpid").toString();
233 nodeId = HexString.toLong(dpid);
234
235 // System.out.println("dpid: " + dpid);
236 }
237 idx++;
238 if (idx == 1) {
239 continue;
240 }
241 int mod = idx % 3;
242 if (mod == 0) {
243 // Setup the incoming port
244 inPort = new Port(portId);
245 continue;
246 }
247 if (mod == 2) {
248 // Setup the outgoing port, and add the Flow Entry
249 outPort = new Port(portId);
250
251 FlowEntry flowEntry = new FlowEntry();
252 flowEntry.setDpid(new Dpid(nodeId));
253 flowEntry.setInPort(inPort);
254 flowEntry.setOutPort(outPort);
255 flowEntry.setFlowEntryMatch(new FlowEntryMatch());
256 flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
257
258 // Set the outgoing port output action
259 ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
260 if (flowEntryActions == null) {
261 flowEntryActions = new ArrayList<FlowEntryAction>();
262 flowEntry.setFlowEntryActions(flowEntryActions);
263 }
264 FlowEntryAction flowEntryAction = new FlowEntryAction();
265 flowEntryAction.setActionOutput(flowEntry.outPort());
266 flowEntryActions.add(flowEntryAction);
267 dataPath.flowEntries().add(flowEntry);
268 continue;
269 }
270 }
271 if (idx > 0) {
272 // Add the last Flow Entry
273 FlowEntry flowEntry = new FlowEntry();
274 flowEntry.setDpid(new Dpid(nodeId));
275 flowEntry.setInPort(inPort);
276 flowEntry.setOutPort(new Port(dest_port.getNumber()));
277 flowEntry.setFlowEntryMatch(new FlowEntryMatch());
278 flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
279
280 // Set the outgoing port output action
281 ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
282 if (flowEntryActions == null) {
283 flowEntryActions = new ArrayList<FlowEntryAction>();
284 flowEntry.setFlowEntryActions(flowEntryActions);
285 }
286 FlowEntryAction flowEntryAction = new FlowEntryAction();
287 flowEntryAction.setActionOutput(flowEntry.outPort());
288 flowEntryActions.add(flowEntryAction);
289 dataPath.flowEntries().add(flowEntry);
290 dataPath.flowEntries().add(flowEntry);
291 }
292
293
294 if (dataPath.flowEntries().size() > 0) {
295 FlowPath flowPath = new FlowPath();
296 flowPath.setDataPath(dataPath);
297
298 return flowPath;
299 }
300 return null;
301
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700302 }
303
304 @Override
305 public Iterable<FlowEntry> getFlowEntries(FlowPath flow) {
306 // TODO Auto-generated method stub
307 return null;
308 }
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700309
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700310
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700311 @Override
Pavlin Radoslavov2b8e6222013-04-03 11:05:01 -0700312 public boolean installRemoteFlowEntry(FlowPath flowPath,
313 FlowEntry entry) {
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700314 // TODO Auto-generated method stub
315 return false;
316 }
317
318 @Override
Pavlin Radoslavov2b8e6222013-04-03 11:05:01 -0700319 public boolean removeRemoteFlowEntry(FlowPath flowPath,
320 FlowEntry entry) {
Pankaj Berde83d83382013-03-28 13:55:34 -0700321 return false;
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700322 // TODO Auto-generated method stub
323
324 }
325
Pankaj Berdeb4bdf702013-03-28 13:37:24 -0700326 @Override
Pavlin Radoslavov2b8e6222013-04-03 11:05:01 -0700327 public boolean installFlowEntry(IOFSwitch mySwitch,
328 FlowPath flowPath,
329 FlowEntry flowEntry) {
Pankaj Berdeb4bdf702013-03-28 13:37:24 -0700330 // TODO Auto-generated method stub
331 return false;
332 }
333
334 @Override
Pavlin Radoslavov2b8e6222013-04-03 11:05:01 -0700335 public boolean removeFlowEntry(IOFSwitch mySwitch,
336 FlowPath flowPath,
337 FlowEntry flowEntry) {
Pankaj Berdeb4bdf702013-03-28 13:37:24 -0700338 // TODO Auto-generated method stub
339 return false;
340 }
Pankaj Berde37f037f2013-04-03 11:52:11 -0700341
Pankaj Berdeb4bdf702013-03-28 13:37:24 -0700342
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700343}