blob: bf5ce518930ba1994fc29a158f8afcb5968afba8 [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;
yoshi2fd4c7e2013-11-22 15:47:55 -080021import net.onrc.onos.graph.DBOperation;
Pankaj Berde38646d62013-06-21 11:34:04 -070022import 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
39 protected static Logger log = LoggerFactory.getLogger(LocalTopologyEventListener.class);
yoshi2fd4c7e2013-11-22 15:47:55 -080040 protected DBOperation 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();
yoshi2fd4c7e2013-11-22 15:47:55 -080088 IPortObject src = op.searchPort(src_dpid, src_port);
89 IPortObject dst = op.searchPort(dst_dpid, dst_port);
Pankaj Berde37f037f2013-04-03 11:52:11 -070090 if (src != null && dst != null) {
91 FlowPath newFlow = this.computeFlowPath(src,dst);
92 installFlow(newFlow);
93 removeFlow(flow);
94 }
95
96 }
97
98 private void removeFlow(IFlowPath flow) {
99 // TODO Auto-generated method stub
100
101 }
102
103 private void installFlow(FlowPath newFlow) {
104 // TODO Auto-generated method stub
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700105
106 }
107
108 @Override
109 public void reconcileFlow(IPortObject src_port, IPortObject dest_port) {
110 // TODO Auto-generated method stub
111
112 }
113
114 @Override
115 public FlowPath computeFlowPath(IPortObject src_port, IPortObject dest_port) {
116 // TODO Auto-generated method stub
Pankaj Berde37f037f2013-04-03 11:52:11 -0700117 DataPath dataPath = new DataPath();
118
119 // FIXME: Bad idea to use FloodLight data structures (SwitchPort)
120
121 dataPath.setSrcPort(new SwitchPort(new Dpid(src_port.getSwitch().getDPID()),
122 new Port(src_port.getNumber())));
123 dataPath.setDstPort(new SwitchPort(new Dpid(src_port.getSwitch().getDPID()),
124 new Port(src_port.getNumber())));
125
126 if (src_port.getSwitch().equals(dest_port.getSwitch())) {
127 // on same switch create quick path
128 FlowEntry flowEntry = new FlowEntry();
129 flowEntry.setDpid(new Dpid(src_port.getSwitch().getDPID()));
130 flowEntry.setInPort(new Port(src_port.getNumber()));
131 flowEntry.setOutPort(new Port(src_port.getNumber()));
132 flowEntry.setFlowEntryMatch(new FlowEntryMatch());
133 flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700134
Pankaj Berde37f037f2013-04-03 11:52:11 -0700135 // Set the outgoing port output action
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700136 FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
Pankaj Berde37f037f2013-04-03 11:52:11 -0700137 FlowEntryAction flowEntryAction = new FlowEntryAction();
138 flowEntryAction.setActionOutput(flowEntry.outPort());
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700139 flowEntryActions.addAction(flowEntryAction);
Pankaj Berde37f037f2013-04-03 11:52:11 -0700140 dataPath.flowEntries().add(flowEntry);
141
142 FlowPath flowPath = new FlowPath();
143 flowPath.setDataPath(dataPath);
144
145 return flowPath;
146 }
147 Vertex v_src = src_port.getSwitch().asVertex();
148 Vertex v_dest = dest_port.getSwitch().asVertex();
149
150 //
151 // Implement the Shortest Path computation by using Breath First Search
152 //
153 Set<Vertex> visitedSet = new HashSet<Vertex>();
154 Queue<Vertex> processingList = new LinkedList<Vertex>();
155 Map<Vertex, Vertex> previousVertexMap = new HashMap<Vertex, Vertex>();
156
157 processingList.add(v_src);
158 visitedSet.add(v_src);
159 Boolean path_found = false;
160 while (! processingList.isEmpty()) {
161 Vertex nextVertex = processingList.poll();
162 if (v_dest.equals(nextVertex)) {
163 path_found = true;
164 break;
165 }
166 for (Vertex parentPort : nextVertex.getVertices(Direction.OUT, "on")) {
167 for (Vertex childPort : parentPort.getVertices(Direction.OUT, "link")) {
168 for (Vertex child : childPort.getVertices(Direction.IN, "on")) {
169 // Ignore inactive switches
170 String state = child.getProperty("state").toString();
171 if (! state.equals(SwitchState.ACTIVE.toString()))
172 continue;
173
174 if (! visitedSet.contains(child)) {
175 previousVertexMap.put(parentPort, nextVertex);
176 previousVertexMap.put(childPort, parentPort);
177 previousVertexMap.put(child, childPort);
178 visitedSet.add(child);
179 processingList.add(child);
180 }
181 }
182 }
183 }
184 }
185 if (! path_found) {
186 return null; // No path found
187 }
188
189 List<Vertex> resultPath = new LinkedList<Vertex>();
190 Vertex previousVertex = v_dest;
191 resultPath.add(v_dest);
192 while (! v_src.equals(previousVertex)) {
193 Vertex currentVertex = previousVertexMap.get(previousVertex);
194 resultPath.add(currentVertex);
195 previousVertex = currentVertex;
196 }
197 Collections.reverse(resultPath);
198
199 // Loop through the result and prepare the return result
200 // as a list of Flow Entries.
201 //
202 long nodeId = 0;
203 short portId = 0;
204 Port inPort = new Port(src_port.getNumber());
205 Port outPort = new Port();
206 int idx = 0;
207 for (Vertex v: resultPath) {
208 String type = v.getProperty("type").toString();
209 // System.out.println("type: " + type);
210 if (type.equals("port")) {
211 String number = v.getProperty("number").toString();
212 // System.out.println("number: " + number);
213
214 Object obj = v.getProperty("number");
215 // String class_str = obj.getClass().toString();
216 if (obj instanceof Short) {
217 portId = (Short)obj;
218 } else if (obj instanceof Integer) {
219 Integer int_nodeId = (Integer)obj;
220 portId = int_nodeId.shortValue();
221 // int int_nodeId = (Integer)obj;
222 // portId = (short)int_nodeId.;
223 }
224 } else if (type.equals("switch")) {
225 String dpid = v.getProperty("dpid").toString();
226 nodeId = HexString.toLong(dpid);
227
228 // System.out.println("dpid: " + dpid);
229 }
230 idx++;
231 if (idx == 1) {
232 continue;
233 }
234 int mod = idx % 3;
235 if (mod == 0) {
236 // Setup the incoming port
237 inPort = new Port(portId);
238 continue;
239 }
240 if (mod == 2) {
241 // Setup the outgoing port, and add the Flow Entry
242 outPort = new Port(portId);
243
244 FlowEntry flowEntry = new FlowEntry();
245 flowEntry.setDpid(new Dpid(nodeId));
246 flowEntry.setInPort(inPort);
247 flowEntry.setOutPort(outPort);
248 flowEntry.setFlowEntryMatch(new FlowEntryMatch());
249 flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
250
251 // Set the outgoing port output action
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700252 FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
Pankaj Berde37f037f2013-04-03 11:52:11 -0700253 FlowEntryAction flowEntryAction = new FlowEntryAction();
254 flowEntryAction.setActionOutput(flowEntry.outPort());
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700255 flowEntryActions.addAction(flowEntryAction);
Pankaj Berde37f037f2013-04-03 11:52:11 -0700256 dataPath.flowEntries().add(flowEntry);
257 continue;
258 }
259 }
260 if (idx > 0) {
261 // Add the last Flow Entry
262 FlowEntry flowEntry = new FlowEntry();
263 flowEntry.setDpid(new Dpid(nodeId));
264 flowEntry.setInPort(inPort);
265 flowEntry.setOutPort(new Port(dest_port.getNumber()));
266 flowEntry.setFlowEntryMatch(new FlowEntryMatch());
267 flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
268
269 // Set the outgoing port output action
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700270 FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
Pankaj Berde37f037f2013-04-03 11:52:11 -0700271 FlowEntryAction flowEntryAction = new FlowEntryAction();
272 flowEntryAction.setActionOutput(flowEntry.outPort());
Pavlin Radoslavov1bc2c472013-07-17 18:11:37 -0700273 flowEntryActions.addAction(flowEntryAction);
Pankaj Berde37f037f2013-04-03 11:52:11 -0700274 dataPath.flowEntries().add(flowEntry);
275 dataPath.flowEntries().add(flowEntry);
276 }
277
278
279 if (dataPath.flowEntries().size() > 0) {
280 FlowPath flowPath = new FlowPath();
281 flowPath.setDataPath(dataPath);
282
283 return flowPath;
284 }
285 return null;
286
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700287 }
288
289 @Override
290 public Iterable<FlowEntry> getFlowEntries(FlowPath flow) {
291 // TODO Auto-generated method stub
292 return null;
293 }
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700294
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700295
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700296 @Override
Pavlin Radoslavov2b8e6222013-04-03 11:05:01 -0700297 public boolean installRemoteFlowEntry(FlowPath flowPath,
298 FlowEntry entry) {
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700299 // TODO Auto-generated method stub
300 return false;
301 }
302
303 @Override
Pavlin Radoslavov2b8e6222013-04-03 11:05:01 -0700304 public boolean removeRemoteFlowEntry(FlowPath flowPath,
305 FlowEntry entry) {
Pankaj Berde83d83382013-03-28 13:55:34 -0700306 return false;
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700307 // TODO Auto-generated method stub
308
309 }
310
Pankaj Berdeb4bdf702013-03-28 13:37:24 -0700311 @Override
Pavlin Radoslavov2b8e6222013-04-03 11:05:01 -0700312 public boolean installFlowEntry(IOFSwitch mySwitch,
313 FlowPath flowPath,
314 FlowEntry flowEntry) {
Pankaj Berdeb4bdf702013-03-28 13:37:24 -0700315 // TODO Auto-generated method stub
316 return false;
317 }
318
319 @Override
Pavlin Radoslavov2b8e6222013-04-03 11:05:01 -0700320 public boolean removeFlowEntry(IOFSwitch mySwitch,
321 FlowPath flowPath,
322 FlowEntry flowEntry) {
Pankaj Berdeb4bdf702013-03-28 13:37:24 -0700323 // TODO Auto-generated method stub
324 return false;
325 }
Pankaj Berde37f037f2013-04-03 11:52:11 -0700326
Pankaj Berdeb4bdf702013-03-28 13:37:24 -0700327
Pankaj Berdefc30d3f2013-03-28 13:34:44 -0700328}