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