blob: 9865debbd4487f48a942a7498082bb67f9829891 [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;
Pankaj Berde38646d62013-06-21 11:34:04 -070021import net.onrc.onos.graph.GraphDBOperation;
22import net.onrc.onos.graph.LocalTopologyEventListener;
HIGUCHI Yuta20514902013-06-12 11:24:16 -070023import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
24import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
25import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
26import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
HIGUCHI Yuta356086e2013-06-12 15:21:19 -070027import net.onrc.onos.ofcontroller.util.DataPath;
28import net.onrc.onos.ofcontroller.util.Dpid;
29import net.onrc.onos.ofcontroller.util.FlowEntry;
30import net.onrc.onos.ofcontroller.util.FlowEntryAction;
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -070031import net.onrc.onos.ofcontroller.util.FlowEntryActions;
HIGUCHI Yuta356086e2013-06-12 15:21:19 -070032import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
33import net.onrc.onos.ofcontroller.util.FlowPath;
34import net.onrc.onos.ofcontroller.util.Port;
35import net.onrc.onos.ofcontroller.util.SwitchPort;
Pankaj Berdefc30d3f2013-03-28 13:34:44 -070036
37public class FlowManagerImpl implements IFlowManager {
Pankaj Berde37f037f2013-04-03 11:52:11 -070038
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070039 protected final static Logger log = LoggerFactory.getLogger(LocalTopologyEventListener.class);
Toshio Koide57b99b52013-06-13 14:09:23 -070040 protected GraphDBOperation op;
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;
Toshio Koide57b99b52013-06-13 14:09:23 -070090 src = op.searchPort(src_dpid, src_port);
91 dst = op.searchPort(dst_dpid, dst_port);
Pankaj Berde37f037f2013-04-03 11:52:11 -070092 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());
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700136
Pankaj Berde37f037f2013-04-03 11:52:11 -0700137 // Set the outgoing port output action
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700138 FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
Pankaj Berde37f037f2013-04-03 11:52:11 -0700139 FlowEntryAction flowEntryAction = new FlowEntryAction();
140 flowEntryAction.setActionOutput(flowEntry.outPort());
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700141 flowEntryActions.addAction(flowEntryAction);
Pankaj Berde37f037f2013-04-03 11:52:11 -0700142 dataPath.flowEntries().add(flowEntry);
143
144 FlowPath flowPath = new FlowPath();
145 flowPath.setDataPath(dataPath);
146
147 return flowPath;
148 }
149 Vertex v_src = src_port.getSwitch().asVertex();
150 Vertex v_dest = dest_port.getSwitch().asVertex();
151
152 //
153 // Implement the Shortest Path computation by using Breath First Search
154 //
155 Set<Vertex> visitedSet = new HashSet<Vertex>();
156 Queue<Vertex> processingList = new LinkedList<Vertex>();
157 Map<Vertex, Vertex> previousVertexMap = new HashMap<Vertex, Vertex>();
158
159 processingList.add(v_src);
160 visitedSet.add(v_src);
161 Boolean path_found = false;
162 while (! processingList.isEmpty()) {
163 Vertex nextVertex = processingList.poll();
164 if (v_dest.equals(nextVertex)) {
165 path_found = true;
166 break;
167 }
168 for (Vertex parentPort : nextVertex.getVertices(Direction.OUT, "on")) {
169 for (Vertex childPort : parentPort.getVertices(Direction.OUT, "link")) {
170 for (Vertex child : childPort.getVertices(Direction.IN, "on")) {
171 // Ignore inactive switches
172 String state = child.getProperty("state").toString();
173 if (! state.equals(SwitchState.ACTIVE.toString()))
174 continue;
175
176 if (! visitedSet.contains(child)) {
177 previousVertexMap.put(parentPort, nextVertex);
178 previousVertexMap.put(childPort, parentPort);
179 previousVertexMap.put(child, childPort);
180 visitedSet.add(child);
181 processingList.add(child);
182 }
183 }
184 }
185 }
186 }
187 if (! path_found) {
188 return null; // No path found
189 }
190
191 List<Vertex> resultPath = new LinkedList<Vertex>();
192 Vertex previousVertex = v_dest;
193 resultPath.add(v_dest);
194 while (! v_src.equals(previousVertex)) {
195 Vertex currentVertex = previousVertexMap.get(previousVertex);
196 resultPath.add(currentVertex);
197 previousVertex = currentVertex;
198 }
199 Collections.reverse(resultPath);
200
201 // Loop through the result and prepare the return result
202 // as a list of Flow Entries.
203 //
204 long nodeId = 0;
205 short portId = 0;
206 Port inPort = new Port(src_port.getNumber());
207 Port outPort = new Port();
208 int idx = 0;
209 for (Vertex v: resultPath) {
210 String type = v.getProperty("type").toString();
211 // System.out.println("type: " + type);
212 if (type.equals("port")) {
Yuta HIGUCHI6f0e4392013-10-09 17:43:34 -0700213 //String number = v.getProperty("number").toString();
Pankaj Berde37f037f2013-04-03 11:52:11 -0700214 // System.out.println("number: " + number);
215
216 Object obj = v.getProperty("number");
217 // String class_str = obj.getClass().toString();
218 if (obj instanceof Short) {
219 portId = (Short)obj;
220 } else if (obj instanceof Integer) {
221 Integer int_nodeId = (Integer)obj;
222 portId = int_nodeId.shortValue();
223 // int int_nodeId = (Integer)obj;
224 // portId = (short)int_nodeId.;
225 }
226 } else if (type.equals("switch")) {
227 String dpid = v.getProperty("dpid").toString();
228 nodeId = HexString.toLong(dpid);
229
230 // System.out.println("dpid: " + dpid);
231 }
232 idx++;
233 if (idx == 1) {
234 continue;
235 }
236 int mod = idx % 3;
237 if (mod == 0) {
238 // Setup the incoming port
239 inPort = new Port(portId);
240 continue;
241 }
242 if (mod == 2) {
243 // Setup the outgoing port, and add the Flow Entry
244 outPort = new Port(portId);
245
246 FlowEntry flowEntry = new FlowEntry();
247 flowEntry.setDpid(new Dpid(nodeId));
248 flowEntry.setInPort(inPort);
249 flowEntry.setOutPort(outPort);
250 flowEntry.setFlowEntryMatch(new FlowEntryMatch());
251 flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
252
253 // Set the outgoing port output action
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700254 FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
Pankaj Berde37f037f2013-04-03 11:52:11 -0700255 FlowEntryAction flowEntryAction = new FlowEntryAction();
256 flowEntryAction.setActionOutput(flowEntry.outPort());
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700257 flowEntryActions.addAction(flowEntryAction);
Pankaj Berde37f037f2013-04-03 11:52:11 -0700258 dataPath.flowEntries().add(flowEntry);
259 continue;
260 }
261 }
262 if (idx > 0) {
263 // Add the last Flow Entry
264 FlowEntry flowEntry = new FlowEntry();
265 flowEntry.setDpid(new Dpid(nodeId));
266 flowEntry.setInPort(inPort);
267 flowEntry.setOutPort(new Port(dest_port.getNumber()));
268 flowEntry.setFlowEntryMatch(new FlowEntryMatch());
269 flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
270
271 // Set the outgoing port output action
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700272 FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
Pankaj Berde37f037f2013-04-03 11:52:11 -0700273 FlowEntryAction flowEntryAction = new FlowEntryAction();
274 flowEntryAction.setActionOutput(flowEntry.outPort());
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700275 flowEntryActions.addAction(flowEntryAction);
Pankaj Berde37f037f2013-04-03 11:52:11 -0700276 dataPath.flowEntries().add(flowEntry);
Brian O'Connor0d6ba512013-11-05 15:17:44 -0800277 // TODO (BOC): why is this twice?
Pankaj Berde37f037f2013-04-03 11:52:11 -0700278 dataPath.flowEntries().add(flowEntry);
279 }
280
281
282 if (dataPath.flowEntries().size() > 0) {
283 FlowPath flowPath = new FlowPath();
284 flowPath.setDataPath(dataPath);
285
286 return flowPath;
287 }
288 return null;
289
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700290 }
291
292 @Override
293 public Iterable<FlowEntry> getFlowEntries(FlowPath flow) {
294 // TODO Auto-generated method stub
295 return null;
296 }
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700297
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700298
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700299 @Override
Pavlin Radoslavov2b8e6222013-04-03 11:05:01 -0700300 public boolean installRemoteFlowEntry(FlowPath flowPath,
301 FlowEntry entry) {
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700302 // TODO Auto-generated method stub
303 return false;
304 }
305
306 @Override
Pavlin Radoslavov2b8e6222013-04-03 11:05:01 -0700307 public boolean removeRemoteFlowEntry(FlowPath flowPath,
308 FlowEntry entry) {
Pankaj Berde83d83382013-03-28 13:55:34 -0700309 return false;
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700310 // TODO Auto-generated method stub
311
312 }
313
Pankaj Berdeb4bdf702013-03-28 13:37:24 -0700314 @Override
Pavlin Radoslavov2b8e6222013-04-03 11:05:01 -0700315 public boolean installFlowEntry(IOFSwitch mySwitch,
316 FlowPath flowPath,
317 FlowEntry flowEntry) {
Pankaj Berdeb4bdf702013-03-28 13:37:24 -0700318 // TODO Auto-generated method stub
319 return false;
320 }
321
322 @Override
Pavlin Radoslavov2b8e6222013-04-03 11:05:01 -0700323 public boolean removeFlowEntry(IOFSwitch mySwitch,
324 FlowPath flowPath,
325 FlowEntry flowEntry) {
Pankaj Berdeb4bdf702013-03-28 13:37:24 -0700326 // TODO Auto-generated method stub
327 return false;
328 }
Pankaj Berde37f037f2013-04-03 11:52:11 -0700329
Pankaj Berdeb4bdf702013-03-28 13:37:24 -0700330
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700331}