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