blob: 532477a580c0c571273d3059da7c7f36c7c838a9 [file] [log] [blame]
Naoki Shiotaaea88582013-11-12 17:58:34 -08001package net.onrc.onos.ofcontroller.flowprogrammer;
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -07002
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -07003import java.io.IOException;
Naoki Shiota7d0cf272013-11-05 10:18:12 -08004import java.util.ArrayDeque;
5import java.util.ArrayList;
6import java.util.EnumSet;
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -07007import java.util.HashMap;
Naoki Shiota7d0cf272013-11-05 10:18:12 -08008import java.util.List;
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -07009import java.util.Map;
Naoki Shiota5c8d19f2013-11-05 15:52:38 -080010import java.util.Set;
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070011
Naoki Shiota7d0cf272013-11-05 10:18:12 -080012import org.openflow.protocol.*;
13import org.openflow.protocol.action.*;
14import org.openflow.protocol.factory.BasicFactory;
15import org.slf4j.Logger;
16import org.slf4j.LoggerFactory;
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070017
18import net.floodlightcontroller.core.FloodlightContext;
19import net.floodlightcontroller.core.IOFSwitch;
Naoki Shiota2e2fc2b2013-11-12 11:21:36 -080020import net.floodlightcontroller.util.MACAddress;
Naoki Shiota7d0cf272013-11-05 10:18:12 -080021import net.floodlightcontroller.util.OFMessageDamper;
22import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
23import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
24import net.onrc.onos.ofcontroller.util.FlowEntryAction;
25import net.onrc.onos.ofcontroller.util.FlowEntryAction.*;
Naoki Shiota2e2fc2b2013-11-12 11:21:36 -080026import net.onrc.onos.ofcontroller.util.FlowEntry;
Naoki Shiota7d0cf272013-11-05 10:18:12 -080027import net.onrc.onos.ofcontroller.util.FlowEntryActions;
28import net.onrc.onos.ofcontroller.util.FlowEntryId;
Naoki Shiota2e2fc2b2013-11-12 11:21:36 -080029import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
30import net.onrc.onos.ofcontroller.util.FlowEntryUserState;
31import net.onrc.onos.ofcontroller.util.FlowPath;
32import net.onrc.onos.ofcontroller.util.IPv4Net;
33import net.onrc.onos.ofcontroller.util.Port;
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070034
35/**
Naoki Shiota8739faa2013-11-18 17:00:25 -080036 * FlowPusher intermediates FlowManager/FlowSynchronizer and switches to push OpenFlow
37 * messages to switches in proper rate.
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070038 * @author Naoki Shiota
39 *
40 */
Brian O'Connor8c166a72013-11-14 18:41:48 -080041public class FlowPusher implements IFlowPusherService {
Naoki Shiota7d0cf272013-11-05 10:18:12 -080042 private final static Logger log = LoggerFactory.getLogger(FlowPusher.class);
43
44 // NOTE: Below are moved from FlowManager.
45 // TODO: Values copied from elsewhere (class LearningSwitch).
46 // The local copy should go away!
47 //
48 protected static final int OFMESSAGE_DAMPER_CAPACITY = 50000; // TODO: find sweet spot
49 protected static final int OFMESSAGE_DAMPER_TIMEOUT = 250; // ms
Naoki Shiota5c8d19f2013-11-05 15:52:38 -080050
Naoki Shiota7d0bcfa2013-11-13 10:43:33 -080051 // Interval of sleep when queue is empty
52 protected static final long SLEEP_MILLI_SEC = 10;
Naoki Shiota5c8d19f2013-11-05 15:52:38 -080053 protected static final int SLEEP_NANO_SEC = 0;
Naoki Shiota7d0bcfa2013-11-13 10:43:33 -080054
55 // Number of messages sent to switch at once
56 protected static final int MAX_MESSAGE_SEND = 100;
Naoki Shiota7d0cf272013-11-05 10:18:12 -080057
58 public static final short PRIORITY_DEFAULT = 100;
59 public static final short FLOWMOD_DEFAULT_IDLE_TIMEOUT = 0; // infinity
60 public static final short FLOWMOD_DEFAULT_HARD_TIMEOUT = 0; // infinite
61
62 public enum QueueState {
63 READY,
64 SUSPENDED,
65 }
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070066
Naoki Shiota8739faa2013-11-18 17:00:25 -080067 @SuppressWarnings("serial")
Naoki Shiota7d0cf272013-11-05 10:18:12 -080068 private class SwitchQueue extends ArrayDeque<OFMessage> {
69 QueueState state;
70
71 // Max rate of sending message (bytes/sec). 0 implies no limitation.
Naoki Shiota8ee48d52013-11-11 15:51:17 -080072 long max_rate = 0; // 0 indicates no limitation
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070073 long last_sent_time = 0;
74 long last_sent_size = 0;
Naoki Shiota7d0cf272013-11-05 10:18:12 -080075
76 /**
77 * Check if sending rate is within the rate
78 * @param current Current time
79 * @return true if within the rate
80 */
81 boolean isSendable(long current) {
Naoki Shiota8ee48d52013-11-11 15:51:17 -080082 if (max_rate == 0) {
83 // no limitation
84 return true;
85 }
86
Naoki Shiota7d0cf272013-11-05 10:18:12 -080087 long rate = last_sent_size / (current - last_sent_time);
88
89 if (rate < max_rate) {
90 return true;
91 } else {
92 return false;
93 }
94 }
95
Naoki Shiota2e2fc2b2013-11-12 11:21:36 -080096 void logSentData(long current, long size) {
Naoki Shiota7d0cf272013-11-05 10:18:12 -080097 last_sent_time = current;
Naoki Shiota2e2fc2b2013-11-12 11:21:36 -080098 last_sent_size = size;
Naoki Shiota7d0cf272013-11-05 10:18:12 -080099 }
100
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700101 }
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800102
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800103 private OFMessageDamper messageDamper;
Naoki Shiotacf1acca2013-10-31 11:40:32 -0700104
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800105 private FloodlightContext context = null;
106 private BasicFactory factory = null;
Naoki Shiotaf0cddbf2013-11-12 14:59:43 -0800107 private Map<Long, FlowPusherProcess> threadMap = null;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800108
Naoki Shiotaf0cddbf2013-11-12 14:59:43 -0800109 private int number_thread = 1;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800110
Naoki Shiota8739faa2013-11-18 17:00:25 -0800111 /**
112 * Main thread that reads messages from queues and sends them to switches.
113 * @author Naoki Shiota
114 *
115 */
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700116 private class FlowPusherProcess implements Runnable {
Naoki Shiotaf0cddbf2013-11-12 14:59:43 -0800117 private Map<IOFSwitch,SwitchQueue> queues
118 = new HashMap<IOFSwitch,SwitchQueue>();
119
120 private boolean isStopped = false;
121 private boolean isMsgAdded = false;
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800122
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700123 @Override
124 public void run() {
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800125 log.debug("Begin Flow Pusher Process");
Naoki Shiotac2a699a2013-10-31 15:36:01 -0700126
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700127 while (true) {
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800128 Set< Map.Entry<IOFSwitch,SwitchQueue> > entries;
129 synchronized (queues) {
130 entries = queues.entrySet();
131 }
132
133 // Set taint flag to false at this moment.
134 isMsgAdded = false;
135
136 for (Map.Entry<IOFSwitch,SwitchQueue> entry : entries) {
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800137 IOFSwitch sw = entry.getKey();
138 SwitchQueue queue = entry.getValue();
139
Naoki Shiotac2a699a2013-10-31 15:36:01 -0700140 // Skip if queue is suspended
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800141 if (sw == null || queue == null ||
142 queue.state != QueueState.READY) {
Naoki Shiotac2a699a2013-10-31 15:36:01 -0700143 continue;
144 }
145
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800146 // check sending rate and determine it to be sent or not
147 long current_time = System.nanoTime();
Naoki Shiota2e2fc2b2013-11-12 11:21:36 -0800148 long size = 0;
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800149
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800150 synchronized (queue) {
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800151 if (queue.isSendable(current_time)) {
Naoki Shiota7d0bcfa2013-11-13 10:43:33 -0800152 int i = 0;
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800153 while (! queue.isEmpty()) {
Naoki Shiota7d0bcfa2013-11-13 10:43:33 -0800154 // Number of messages excess the limit
155 if (++i >= MAX_MESSAGE_SEND) {
156 // Messages remains in queue
157 isMsgAdded = true;
158 break;
159 }
160
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800161 OFMessage msg = queue.poll();
162
163 // if need to send, call IOFSwitch#write()
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800164 try {
165 messageDamper.write(sw, msg, context);
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800166 log.debug("Pusher sends message : {}", msg);
Naoki Shiotaf0cddbf2013-11-12 14:59:43 -0800167 size += msg.getLength();
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800168 } catch (IOException e) {
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800169 e.printStackTrace();
Naoki Shiota7d0bcfa2013-11-13 10:43:33 -0800170 log.error("Exception in sending message ({}) : {}", msg, e);
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800171 }
172 }
Naoki Shiotaf0cddbf2013-11-12 14:59:43 -0800173 sw.flush();
Naoki Shiota2e2fc2b2013-11-12 11:21:36 -0800174 queue.logSentData(current_time, size);
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700175 }
176 }
177 }
178
179 // sleep while all queues are empty
Naoki Shiota2e2fc2b2013-11-12 11:21:36 -0800180 while (! (isMsgAdded || isStopped)) {
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800181 try {
182 Thread.sleep(SLEEP_MILLI_SEC, SLEEP_NANO_SEC);
183 } catch (InterruptedException e) {
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800184 e.printStackTrace();
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800185 log.error("Thread.sleep failed");
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800186 }
187 }
188
189 log.debug("Exit sleep loop.");
190
191 if (isStopped) {
192 log.debug("Pusher Process finished.");
193 return;
194 }
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800195
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700196 }
197 }
198 }
199
Naoki Shiotaf0cddbf2013-11-12 14:59:43 -0800200 public FlowPusher() {
201
202 }
203
204 public FlowPusher(int number_thread) {
205 this.number_thread = number_thread;
206 }
207
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800208 public void init(FloodlightContext context, BasicFactory factory, OFMessageDamper damper) {
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700209 this.context = context;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800210 this.factory = factory;
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800211
212 if (damper != null) {
213 messageDamper = damper;
214 } else {
215 // use default value
216 messageDamper = new OFMessageDamper(OFMESSAGE_DAMPER_CAPACITY,
217 EnumSet.of(OFType.FLOW_MOD),
218 OFMESSAGE_DAMPER_TIMEOUT);
219 }
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700220 }
Naoki Shiotaf0cddbf2013-11-12 14:59:43 -0800221
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800222 /**
223 * Begin processing queue.
224 */
225 public void start() {
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800226 if (factory == null) {
227 log.error("FlowPusher not yet initialized.");
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800228 return;
229 }
230
Naoki Shiotaf0cddbf2013-11-12 14:59:43 -0800231 threadMap = new HashMap<Long,FlowPusherProcess>();
232 for (long i = 0; i < number_thread; ++i) {
233 FlowPusherProcess runnable = new FlowPusherProcess();
234 threadMap.put(i, runnable);
235
236 Thread thread = new Thread(runnable);
237 thread.start();
238 }
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700239 }
240
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800241 /**
Naoki Shiota8739faa2013-11-18 17:00:25 -0800242 * Suspend sending messages to switch.
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800243 * @param sw
244 */
Brian O'Connor8c166a72013-11-14 18:41:48 -0800245 @Override
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800246 public boolean suspend(IOFSwitch sw) {
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800247 SwitchQueue queue = getQueue(sw);
248
249 if (queue == null) {
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800250 return false;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800251 }
252
253 synchronized (queue) {
254 if (queue.state == QueueState.READY) {
255 queue.state = QueueState.SUSPENDED;
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800256 return true;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800257 }
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800258 return false;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800259 }
260 }
261
262 /**
Naoki Shiota8739faa2013-11-18 17:00:25 -0800263 * Resume sending messages to switch.
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800264 */
Brian O'Connor8c166a72013-11-14 18:41:48 -0800265 @Override
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800266 public boolean resume(IOFSwitch sw) {
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800267 SwitchQueue queue = getQueue(sw);
268
269 if (queue == null) {
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800270 return false;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800271 }
272
273 synchronized (queue) {
274 if (queue.state == QueueState.SUSPENDED) {
275 queue.state = QueueState.READY;
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800276 return true;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800277 }
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800278 return false;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800279 }
280 }
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800281
Naoki Shiota8739faa2013-11-18 17:00:25 -0800282 /**
283 * Check if given switch is suspended.
284 */
Brian O'Connor8c166a72013-11-14 18:41:48 -0800285 @Override
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800286 public boolean isSuspended(IOFSwitch sw) {
287 SwitchQueue queue = getQueue(sw);
288
289 if (queue == null) {
290 // TODO Is true suitable for this case?
291 return true;
292 }
293
294 return (queue.state == QueueState.SUSPENDED);
295 }
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800296
297 /**
Naoki Shiota8739faa2013-11-18 17:00:25 -0800298 * Stop processing queue and exit thread.
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800299 */
300 public void stop() {
Naoki Shiotaf0cddbf2013-11-12 14:59:43 -0800301 if (threadMap == null) {
302 return;
303 }
304
305 for (FlowPusherProcess runnable : threadMap.values()) {
306 if (! runnable.isStopped) {
307 runnable.isStopped = true;
308 }
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800309 }
310 }
311
Naoki Shiota8739faa2013-11-18 17:00:25 -0800312 /**
313 * Set sending rate to a switch.
314 * @param sw Switch.
315 * @param rate Rate in bytes/sec.
316 */
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800317 public void setRate(IOFSwitch sw, long rate) {
318 SwitchQueue queue = getQueue(sw);
319 if (queue == null) {
320 return;
321 }
322
323 if (rate > 0) {
324 queue.max_rate = rate;
Naoki Shiotac2a699a2013-10-31 15:36:01 -0700325 }
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700326 }
Naoki Shiotac2a699a2013-10-31 15:36:01 -0700327
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800328 /**
329 * Add OFMessage to the queue related to given switch.
Naoki Shiota8739faa2013-11-18 17:00:25 -0800330 * @param sw Switch to which message is sent.
331 * @param msg Message to be sent.
332 * @return true if succeed.
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800333 */
Brian O'Connor8c166a72013-11-14 18:41:48 -0800334 @Override
Naoki Shiota2e2fc2b2013-11-12 11:21:36 -0800335 public boolean add(IOFSwitch sw, OFMessage msg) {
Naoki Shiotaf0cddbf2013-11-12 14:59:43 -0800336 FlowPusherProcess proc = getProcess(sw);
337 SwitchQueue queue = proc.queues.get(sw);
338
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800339 if (queue == null) {
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800340 queue = new SwitchQueue();
341 queue.state = QueueState.READY;
Naoki Shiotaf0cddbf2013-11-12 14:59:43 -0800342 synchronized (proc) {
343 proc.queues.put(sw, queue);
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800344 }
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800345 }
346
347 synchronized (queue) {
348 queue.add(msg);
Naoki Shiotaf0cddbf2013-11-12 14:59:43 -0800349 log.debug("Message is pushed : {}", msg);
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800350 }
351
Naoki Shiotaf0cddbf2013-11-12 14:59:43 -0800352 proc.isMsgAdded = true;
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800353
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800354 return true;
355 }
356
357 /**
358 * Create OFMessage from given flow information and add it to the queue.
Naoki Shiota8739faa2013-11-18 17:00:25 -0800359 * @param sw Switch to which message is sent.
360 * @param flowObj FlowPath.
361 * @param flowEntryObj FlowEntry.
362 * @return true if succeed.
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800363 */
Brian O'Connor8c166a72013-11-14 18:41:48 -0800364 @Override
Naoki Shiota2e2fc2b2013-11-12 11:21:36 -0800365 public boolean add(IOFSwitch sw, IFlowPath flowObj, IFlowEntry flowEntryObj) {
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800366 log.debug("sending : {}, {}", sw, flowObj);
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800367 String flowEntryIdStr = flowEntryObj.getFlowEntryId();
368 if (flowEntryIdStr == null)
369 return false;
370 FlowEntryId flowEntryId = new FlowEntryId(flowEntryIdStr);
371 String userState = flowEntryObj.getUserState();
372 if (userState == null)
373 return false;
374
375 //
376 // Create the Open Flow Flow Modification Entry to push
377 //
378 OFFlowMod fm = (OFFlowMod)factory.getMessage(OFType.FLOW_MOD);
379 long cookie = flowEntryId.value();
380
381 short flowModCommand = OFFlowMod.OFPFC_ADD;
382 if (userState.equals("FE_USER_ADD")) {
383 flowModCommand = OFFlowMod.OFPFC_ADD;
384 } else if (userState.equals("FE_USER_MODIFY")) {
385 flowModCommand = OFFlowMod.OFPFC_MODIFY_STRICT;
386 } else if (userState.equals("FE_USER_DELETE")) {
387 flowModCommand = OFFlowMod.OFPFC_DELETE_STRICT;
388 } else {
389 // Unknown user state. Ignore the entry
390 log.debug("Flow Entry ignored (FlowEntryId = {}): unknown user state {}",
391 flowEntryId.toString(), userState);
392 return false;
393 }
394
395 //
396 // Fetch the match conditions.
397 //
398 // NOTE: The Flow matching conditions common for all Flow Entries are
399 // used ONLY if a Flow Entry does NOT have the corresponding matching
400 // condition set.
401 //
402 OFMatch match = new OFMatch();
403 match.setWildcards(OFMatch.OFPFW_ALL);
404
405 // Match the Incoming Port
406 Short matchInPort = flowEntryObj.getMatchInPort();
407 if (matchInPort != null) {
408 match.setInputPort(matchInPort);
409 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_IN_PORT);
410 }
411
412 // Match the Source MAC address
413 String matchSrcMac = flowEntryObj.getMatchSrcMac();
414 if (matchSrcMac == null)
415 matchSrcMac = flowObj.getMatchSrcMac();
416 if (matchSrcMac != null) {
417 match.setDataLayerSource(matchSrcMac);
418 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
419 }
420
421 // Match the Destination MAC address
422 String matchDstMac = flowEntryObj.getMatchDstMac();
423 if (matchDstMac == null)
424 matchDstMac = flowObj.getMatchDstMac();
425 if (matchDstMac != null) {
426 match.setDataLayerDestination(matchDstMac);
427 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
428 }
429
430 // Match the Ethernet Frame Type
431 Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
432 if (matchEthernetFrameType == null)
433 matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
434 if (matchEthernetFrameType != null) {
435 match.setDataLayerType(matchEthernetFrameType);
436 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
437 }
438
439 // Match the VLAN ID
440 Short matchVlanId = flowEntryObj.getMatchVlanId();
441 if (matchVlanId == null)
442 matchVlanId = flowObj.getMatchVlanId();
443 if (matchVlanId != null) {
444 match.setDataLayerVirtualLan(matchVlanId);
445 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN);
446 }
447
448 // Match the VLAN priority
449 Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
450 if (matchVlanPriority == null)
451 matchVlanPriority = flowObj.getMatchVlanPriority();
452 if (matchVlanPriority != null) {
453 match.setDataLayerVirtualLanPriorityCodePoint(matchVlanPriority);
454 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN_PCP);
455 }
456
457 // Match the Source IPv4 Network prefix
458 String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
459 if (matchSrcIPv4Net == null)
460 matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
461 if (matchSrcIPv4Net != null) {
462 match.setFromCIDR(matchSrcIPv4Net, OFMatch.STR_NW_SRC);
463 }
464
465 // Match the Destination IPv4 Network prefix
466 String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
467 if (matchDstIPv4Net == null)
468 matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
469 if (matchDstIPv4Net != null) {
470 match.setFromCIDR(matchDstIPv4Net, OFMatch.STR_NW_DST);
471 }
472
473 // Match the IP protocol
474 Byte matchIpProto = flowEntryObj.getMatchIpProto();
475 if (matchIpProto == null)
476 matchIpProto = flowObj.getMatchIpProto();
477 if (matchIpProto != null) {
478 match.setNetworkProtocol(matchIpProto);
479 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_PROTO);
480 }
481
482 // Match the IP ToS (DSCP field, 6 bits)
483 Byte matchIpToS = flowEntryObj.getMatchIpToS();
484 if (matchIpToS == null)
485 matchIpToS = flowObj.getMatchIpToS();
486 if (matchIpToS != null) {
487 match.setNetworkTypeOfService(matchIpToS);
488 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_TOS);
489 }
490
491 // Match the Source TCP/UDP port
492 Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
493 if (matchSrcTcpUdpPort == null)
494 matchSrcTcpUdpPort = flowObj.getMatchSrcTcpUdpPort();
495 if (matchSrcTcpUdpPort != null) {
496 match.setTransportSource(matchSrcTcpUdpPort);
497 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
498 }
499
500 // Match the Destination TCP/UDP port
501 Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
502 if (matchDstTcpUdpPort == null)
503 matchDstTcpUdpPort = flowObj.getMatchDstTcpUdpPort();
504 if (matchDstTcpUdpPort != null) {
505 match.setTransportDestination(matchDstTcpUdpPort);
506 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_DST);
507 }
508
509 //
510 // Fetch the actions
511 //
512 Short actionOutputPort = null;
513 List<OFAction> openFlowActions = new ArrayList<OFAction>();
514 int actionsLen = 0;
515 FlowEntryActions flowEntryActions = null;
516 String actionsStr = flowEntryObj.getActions();
517 if (actionsStr != null)
518 flowEntryActions = new FlowEntryActions(actionsStr);
519 else
520 flowEntryActions = new FlowEntryActions();
521 for (FlowEntryAction action : flowEntryActions.actions()) {
522 ActionOutput actionOutput = action.actionOutput();
523 ActionSetVlanId actionSetVlanId = action.actionSetVlanId();
524 ActionSetVlanPriority actionSetVlanPriority = action.actionSetVlanPriority();
525 ActionStripVlan actionStripVlan = action.actionStripVlan();
526 ActionSetEthernetAddr actionSetEthernetSrcAddr = action.actionSetEthernetSrcAddr();
527 ActionSetEthernetAddr actionSetEthernetDstAddr = action.actionSetEthernetDstAddr();
528 ActionSetIPv4Addr actionSetIPv4SrcAddr = action.actionSetIPv4SrcAddr();
529 ActionSetIPv4Addr actionSetIPv4DstAddr = action.actionSetIPv4DstAddr();
530 ActionSetIpToS actionSetIpToS = action.actionSetIpToS();
531 ActionSetTcpUdpPort actionSetTcpUdpSrcPort = action.actionSetTcpUdpSrcPort();
532 ActionSetTcpUdpPort actionSetTcpUdpDstPort = action.actionSetTcpUdpDstPort();
533 ActionEnqueue actionEnqueue = action.actionEnqueue();
534
535 if (actionOutput != null) {
536 actionOutputPort = actionOutput.port().value();
537 // XXX: The max length is hard-coded for now
538 OFActionOutput ofa =
539 new OFActionOutput(actionOutput.port().value(),
540 (short)0xffff);
541 openFlowActions.add(ofa);
542 actionsLen += ofa.getLength();
543 }
544
545 if (actionSetVlanId != null) {
546 OFActionVirtualLanIdentifier ofa =
547 new OFActionVirtualLanIdentifier(actionSetVlanId.vlanId());
548 openFlowActions.add(ofa);
549 actionsLen += ofa.getLength();
550 }
551
552 if (actionSetVlanPriority != null) {
553 OFActionVirtualLanPriorityCodePoint ofa =
554 new OFActionVirtualLanPriorityCodePoint(actionSetVlanPriority.vlanPriority());
555 openFlowActions.add(ofa);
556 actionsLen += ofa.getLength();
557 }
558
559 if (actionStripVlan != null) {
560 if (actionStripVlan.stripVlan() == true) {
561 OFActionStripVirtualLan ofa = new OFActionStripVirtualLan();
562 openFlowActions.add(ofa);
563 actionsLen += ofa.getLength();
564 }
565 }
566
567 if (actionSetEthernetSrcAddr != null) {
568 OFActionDataLayerSource ofa =
569 new OFActionDataLayerSource(actionSetEthernetSrcAddr.addr().toBytes());
570 openFlowActions.add(ofa);
571 actionsLen += ofa.getLength();
572 }
573
574 if (actionSetEthernetDstAddr != null) {
575 OFActionDataLayerDestination ofa =
576 new OFActionDataLayerDestination(actionSetEthernetDstAddr.addr().toBytes());
577 openFlowActions.add(ofa);
578 actionsLen += ofa.getLength();
579 }
580
581 if (actionSetIPv4SrcAddr != null) {
582 OFActionNetworkLayerSource ofa =
583 new OFActionNetworkLayerSource(actionSetIPv4SrcAddr.addr().value());
584 openFlowActions.add(ofa);
585 actionsLen += ofa.getLength();
586 }
587
588 if (actionSetIPv4DstAddr != null) {
589 OFActionNetworkLayerDestination ofa =
590 new OFActionNetworkLayerDestination(actionSetIPv4DstAddr.addr().value());
591 openFlowActions.add(ofa);
592 actionsLen += ofa.getLength();
593 }
594
595 if (actionSetIpToS != null) {
596 OFActionNetworkTypeOfService ofa =
597 new OFActionNetworkTypeOfService(actionSetIpToS.ipToS());
598 openFlowActions.add(ofa);
599 actionsLen += ofa.getLength();
600 }
601
602 if (actionSetTcpUdpSrcPort != null) {
603 OFActionTransportLayerSource ofa =
604 new OFActionTransportLayerSource(actionSetTcpUdpSrcPort.port());
605 openFlowActions.add(ofa);
606 actionsLen += ofa.getLength();
607 }
608
609 if (actionSetTcpUdpDstPort != null) {
610 OFActionTransportLayerDestination ofa =
611 new OFActionTransportLayerDestination(actionSetTcpUdpDstPort.port());
612 openFlowActions.add(ofa);
613 actionsLen += ofa.getLength();
614 }
615
616 if (actionEnqueue != null) {
617 OFActionEnqueue ofa =
618 new OFActionEnqueue(actionEnqueue.port().value(),
619 actionEnqueue.queueId());
620 openFlowActions.add(ofa);
621 actionsLen += ofa.getLength();
622 }
623 }
624
625 fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
626 .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
627 .setPriority(PRIORITY_DEFAULT)
628 .setBufferId(OFPacketOut.BUFFER_ID_NONE)
629 .setCookie(cookie)
630 .setCommand(flowModCommand)
631 .setMatch(match)
632 .setActions(openFlowActions)
633 .setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLen);
634 fm.setOutPort(OFPort.OFPP_NONE.getValue());
635 if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
636 (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
637 if (actionOutputPort != null)
638 fm.setOutPort(actionOutputPort);
639 }
640
641 //
642 // TODO: Set the following flag
643 // fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
644 // See method ForwardingBase::pushRoute()
645 //
646
647 //
648 // Write the message to the switch
649 //
650 log.debug("MEASUREMENT: Installing flow entry " + userState +
651 " into switch DPID: " +
652 sw.getStringId() +
653 " flowEntryId: " + flowEntryId.toString() +
654 " srcMac: " + matchSrcMac + " dstMac: " + matchDstMac +
655 " inPort: " + matchInPort + " outPort: " + actionOutputPort
656 );
Naoki Shiota2e2fc2b2013-11-12 11:21:36 -0800657 add(sw,fm);
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800658 //
659 // TODO: We should use the OpenFlow Barrier mechanism
660 // to check for errors, and update the SwitchState
661 // for a flow entry after the Barrier message is
662 // is received.
663 //
664 flowEntryObj.setSwitchState("FE_SWITCH_UPDATED");
665
666 return true;
667 }
668
Naoki Shiota8739faa2013-11-18 17:00:25 -0800669 /**
670 * Create OFMessage from given flow information and add it to the queue.
671 * @param sw Switch to which message is sent.
672 * @param flowPath FlowPath.
673 * @param flowEntry FlowEntry.
674 * @return true if secceed.
675 */
Brian O'Connor8c166a72013-11-14 18:41:48 -0800676 @Override
Naoki Shiota2e2fc2b2013-11-12 11:21:36 -0800677 public boolean add(IOFSwitch sw, FlowPath flowPath, FlowEntry flowEntry) {
678 //
679 // Create the OpenFlow Flow Modification Entry to push
680 //
681 OFFlowMod fm = (OFFlowMod) factory.getMessage(OFType.FLOW_MOD);
682 long cookie = flowEntry.flowEntryId().value();
683
684 short flowModCommand = OFFlowMod.OFPFC_ADD;
685 if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_ADD) {
686 flowModCommand = OFFlowMod.OFPFC_ADD;
687 } else if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_MODIFY) {
688 flowModCommand = OFFlowMod.OFPFC_MODIFY_STRICT;
689 } else if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_DELETE) {
690 flowModCommand = OFFlowMod.OFPFC_DELETE_STRICT;
691 } else {
692 // Unknown user state. Ignore the entry
693 log.debug(
694 "Flow Entry ignored (FlowEntryId = {}): unknown user state {}",
695 flowEntry.flowEntryId().toString(),
696 flowEntry.flowEntryUserState());
697 return false;
698 }
699
700 //
701 // Fetch the match conditions.
702 //
703 // NOTE: The Flow matching conditions common for all Flow Entries are
704 // used ONLY if a Flow Entry does NOT have the corresponding matching
705 // condition set.
706 //
707 OFMatch match = new OFMatch();
708 match.setWildcards(OFMatch.OFPFW_ALL);
709 FlowEntryMatch flowPathMatch = flowPath.flowEntryMatch();
710 FlowEntryMatch flowEntryMatch = flowEntry.flowEntryMatch();
711
712 // Match the Incoming Port
713 Port matchInPort = flowEntryMatch.inPort();
714 if (matchInPort != null) {
715 match.setInputPort(matchInPort.value());
716 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_IN_PORT);
717 }
718
719 // Match the Source MAC address
720 MACAddress matchSrcMac = flowEntryMatch.srcMac();
721 if ((matchSrcMac == null) && (flowPathMatch != null)) {
722 matchSrcMac = flowPathMatch.srcMac();
723 }
724 if (matchSrcMac != null) {
725 match.setDataLayerSource(matchSrcMac.toString());
726 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
727 }
728
729 // Match the Destination MAC address
730 MACAddress matchDstMac = flowEntryMatch.dstMac();
731 if ((matchDstMac == null) && (flowPathMatch != null)) {
732 matchDstMac = flowPathMatch.dstMac();
733 }
734 if (matchDstMac != null) {
735 match.setDataLayerDestination(matchDstMac.toString());
736 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
737 }
738
739 // Match the Ethernet Frame Type
740 Short matchEthernetFrameType = flowEntryMatch.ethernetFrameType();
741 if ((matchEthernetFrameType == null) && (flowPathMatch != null)) {
742 matchEthernetFrameType = flowPathMatch.ethernetFrameType();
743 }
744 if (matchEthernetFrameType != null) {
745 match.setDataLayerType(matchEthernetFrameType);
746 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
747 }
748
749 // Match the VLAN ID
750 Short matchVlanId = flowEntryMatch.vlanId();
751 if ((matchVlanId == null) && (flowPathMatch != null)) {
752 matchVlanId = flowPathMatch.vlanId();
753 }
754 if (matchVlanId != null) {
755 match.setDataLayerVirtualLan(matchVlanId);
756 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN);
757 }
758
759 // Match the VLAN priority
760 Byte matchVlanPriority = flowEntryMatch.vlanPriority();
761 if ((matchVlanPriority == null) && (flowPathMatch != null)) {
762 matchVlanPriority = flowPathMatch.vlanPriority();
763 }
764 if (matchVlanPriority != null) {
765 match.setDataLayerVirtualLanPriorityCodePoint(matchVlanPriority);
766 match.setWildcards(match.getWildcards()
767 & ~OFMatch.OFPFW_DL_VLAN_PCP);
768 }
769
770 // Match the Source IPv4 Network prefix
771 IPv4Net matchSrcIPv4Net = flowEntryMatch.srcIPv4Net();
772 if ((matchSrcIPv4Net == null) && (flowPathMatch != null)) {
773 matchSrcIPv4Net = flowPathMatch.srcIPv4Net();
774 }
775 if (matchSrcIPv4Net != null) {
776 match.setFromCIDR(matchSrcIPv4Net.toString(), OFMatch.STR_NW_SRC);
777 }
778
779 // Natch the Destination IPv4 Network prefix
780 IPv4Net matchDstIPv4Net = flowEntryMatch.dstIPv4Net();
781 if ((matchDstIPv4Net == null) && (flowPathMatch != null)) {
782 matchDstIPv4Net = flowPathMatch.dstIPv4Net();
783 }
784 if (matchDstIPv4Net != null) {
785 match.setFromCIDR(matchDstIPv4Net.toString(), OFMatch.STR_NW_DST);
786 }
787
788 // Match the IP protocol
789 Byte matchIpProto = flowEntryMatch.ipProto();
790 if ((matchIpProto == null) && (flowPathMatch != null)) {
791 matchIpProto = flowPathMatch.ipProto();
792 }
793 if (matchIpProto != null) {
794 match.setNetworkProtocol(matchIpProto);
795 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_PROTO);
796 }
797
798 // Match the IP ToS (DSCP field, 6 bits)
799 Byte matchIpToS = flowEntryMatch.ipToS();
800 if ((matchIpToS == null) && (flowPathMatch != null)) {
801 matchIpToS = flowPathMatch.ipToS();
802 }
803 if (matchIpToS != null) {
804 match.setNetworkTypeOfService(matchIpToS);
805 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_TOS);
806 }
807
808 // Match the Source TCP/UDP port
809 Short matchSrcTcpUdpPort = flowEntryMatch.srcTcpUdpPort();
810 if ((matchSrcTcpUdpPort == null) && (flowPathMatch != null)) {
811 matchSrcTcpUdpPort = flowPathMatch.srcTcpUdpPort();
812 }
813 if (matchSrcTcpUdpPort != null) {
814 match.setTransportSource(matchSrcTcpUdpPort);
815 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
816 }
817
818 // Match the Destination TCP/UDP port
819 Short matchDstTcpUdpPort = flowEntryMatch.dstTcpUdpPort();
820 if ((matchDstTcpUdpPort == null) && (flowPathMatch != null)) {
821 matchDstTcpUdpPort = flowPathMatch.dstTcpUdpPort();
822 }
823 if (matchDstTcpUdpPort != null) {
824 match.setTransportDestination(matchDstTcpUdpPort);
825 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_DST);
826 }
827
828 //
829 // Fetch the actions
830 //
831 Short actionOutputPort = null;
832 List<OFAction> openFlowActions = new ArrayList<OFAction>();
833 int actionsLen = 0;
834 FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
835 //
836 for (FlowEntryAction action : flowEntryActions.actions()) {
837 ActionOutput actionOutput = action.actionOutput();
838 ActionSetVlanId actionSetVlanId = action.actionSetVlanId();
839 ActionSetVlanPriority actionSetVlanPriority = action
840 .actionSetVlanPriority();
841 ActionStripVlan actionStripVlan = action.actionStripVlan();
842 ActionSetEthernetAddr actionSetEthernetSrcAddr = action
843 .actionSetEthernetSrcAddr();
844 ActionSetEthernetAddr actionSetEthernetDstAddr = action
845 .actionSetEthernetDstAddr();
846 ActionSetIPv4Addr actionSetIPv4SrcAddr = action
847 .actionSetIPv4SrcAddr();
848 ActionSetIPv4Addr actionSetIPv4DstAddr = action
849 .actionSetIPv4DstAddr();
850 ActionSetIpToS actionSetIpToS = action.actionSetIpToS();
851 ActionSetTcpUdpPort actionSetTcpUdpSrcPort = action
852 .actionSetTcpUdpSrcPort();
853 ActionSetTcpUdpPort actionSetTcpUdpDstPort = action
854 .actionSetTcpUdpDstPort();
855 ActionEnqueue actionEnqueue = action.actionEnqueue();
856
857 if (actionOutput != null) {
858 actionOutputPort = actionOutput.port().value();
859 // XXX: The max length is hard-coded for now
860 OFActionOutput ofa = new OFActionOutput(actionOutput.port()
861 .value(), (short) 0xffff);
862 openFlowActions.add(ofa);
863 actionsLen += ofa.getLength();
864 }
865
866 if (actionSetVlanId != null) {
867 OFActionVirtualLanIdentifier ofa = new OFActionVirtualLanIdentifier(
868 actionSetVlanId.vlanId());
869 openFlowActions.add(ofa);
870 actionsLen += ofa.getLength();
871 }
872
873 if (actionSetVlanPriority != null) {
874 OFActionVirtualLanPriorityCodePoint ofa = new OFActionVirtualLanPriorityCodePoint(
875 actionSetVlanPriority.vlanPriority());
876 openFlowActions.add(ofa);
877 actionsLen += ofa.getLength();
878 }
879
880 if (actionStripVlan != null) {
881 if (actionStripVlan.stripVlan() == true) {
882 OFActionStripVirtualLan ofa = new OFActionStripVirtualLan();
883 openFlowActions.add(ofa);
884 actionsLen += ofa.getLength();
885 }
886 }
887
888 if (actionSetEthernetSrcAddr != null) {
889 OFActionDataLayerSource ofa = new OFActionDataLayerSource(
890 actionSetEthernetSrcAddr.addr().toBytes());
891 openFlowActions.add(ofa);
892 actionsLen += ofa.getLength();
893 }
894
895 if (actionSetEthernetDstAddr != null) {
896 OFActionDataLayerDestination ofa = new OFActionDataLayerDestination(
897 actionSetEthernetDstAddr.addr().toBytes());
898 openFlowActions.add(ofa);
899 actionsLen += ofa.getLength();
900 }
901
902 if (actionSetIPv4SrcAddr != null) {
903 OFActionNetworkLayerSource ofa = new OFActionNetworkLayerSource(
904 actionSetIPv4SrcAddr.addr().value());
905 openFlowActions.add(ofa);
906 actionsLen += ofa.getLength();
907 }
908
909 if (actionSetIPv4DstAddr != null) {
910 OFActionNetworkLayerDestination ofa = new OFActionNetworkLayerDestination(
911 actionSetIPv4DstAddr.addr().value());
912 openFlowActions.add(ofa);
913 actionsLen += ofa.getLength();
914 }
915
916 if (actionSetIpToS != null) {
917 OFActionNetworkTypeOfService ofa = new OFActionNetworkTypeOfService(
918 actionSetIpToS.ipToS());
919 openFlowActions.add(ofa);
920 actionsLen += ofa.getLength();
921 }
922
923 if (actionSetTcpUdpSrcPort != null) {
924 OFActionTransportLayerSource ofa = new OFActionTransportLayerSource(
925 actionSetTcpUdpSrcPort.port());
926 openFlowActions.add(ofa);
927 actionsLen += ofa.getLength();
928 }
929
930 if (actionSetTcpUdpDstPort != null) {
931 OFActionTransportLayerDestination ofa = new OFActionTransportLayerDestination(
932 actionSetTcpUdpDstPort.port());
933 openFlowActions.add(ofa);
934 actionsLen += ofa.getLength();
935 }
936
937 if (actionEnqueue != null) {
938 OFActionEnqueue ofa = new OFActionEnqueue(actionEnqueue.port()
939 .value(), actionEnqueue.queueId());
940 openFlowActions.add(ofa);
941 actionsLen += ofa.getLength();
942 }
943 }
944
945 fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
946 .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
947 .setPriority(PRIORITY_DEFAULT)
948 .setBufferId(OFPacketOut.BUFFER_ID_NONE).setCookie(cookie)
949 .setCommand(flowModCommand).setMatch(match)
950 .setActions(openFlowActions)
951 .setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLen);
952 fm.setOutPort(OFPort.OFPP_NONE.getValue());
953 if ((flowModCommand == OFFlowMod.OFPFC_DELETE)
954 || (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
955 if (actionOutputPort != null)
956 fm.setOutPort(actionOutputPort);
957 }
958
959 //
960 // TODO: Set the following flag
961 // fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
962 // See method ForwardingBase::pushRoute()
963 //
964
965 //
966 // Write the message to the switch
967 //
968 log.debug("MEASUREMENT: Installing flow entry "
969 + flowEntry.flowEntryUserState() + " into switch DPID: "
970 + sw.getStringId() + " flowEntryId: "
971 + flowEntry.flowEntryId().toString() + " srcMac: "
972 + matchSrcMac + " dstMac: " + matchDstMac + " inPort: "
973 + matchInPort + " outPort: " + actionOutputPort);
974
975 //
976 // TODO: We should use the OpenFlow Barrier mechanism
977 // to check for errors, and update the SwitchState
978 // for a flow entry after the Barrier message is
979 // is received.
980 //
981 // TODO: The FlowEntry Object in Titan should be set
982 // to FE_SWITCH_UPDATED.
983 //
984
985 return add(sw,fm);
986 }
987
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800988 private SwitchQueue getQueue(IOFSwitch sw) {
989 if (sw == null) {
990 return null;
991 }
992
Naoki Shiotaf0cddbf2013-11-12 14:59:43 -0800993 return getProcess(sw).queues.get(sw);
994 }
995
996 private long getHash(IOFSwitch sw) {
997 // TODO should consider equalization algorithm
998 return sw.getId() % number_thread;
999 }
1000
1001 private FlowPusherProcess getProcess(IOFSwitch sw) {
1002 long hash = getHash(sw);
1003
1004 return threadMap.get(hash);
Naoki Shiota7d0cf272013-11-05 10:18:12 -08001005 }
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -07001006}