blob: 67d84e29a5540a23327b2c6ad54e5a21a8951413 [file] [log] [blame]
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -07001package net.onrc.onos.ofcontroller.flowmanager;
2
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 Shiota7d0cf272013-11-05 10:18:12 -080020import net.floodlightcontroller.util.OFMessageDamper;
21import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
22import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
23import net.onrc.onos.ofcontroller.util.FlowEntryAction;
24import net.onrc.onos.ofcontroller.util.FlowEntryAction.*;
25import net.onrc.onos.ofcontroller.util.FlowEntryActions;
26import net.onrc.onos.ofcontroller.util.FlowEntryId;
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070027
28/**
29 * FlowPusher intermediates flow_mod sent from FlowManager/FlowSync to switches.
30 * FlowPusher controls the rate of sending flow_mods so that connection doesn't overflow.
31 * @author Naoki Shiota
32 *
33 */
34public class FlowPusher {
Naoki Shiota7d0cf272013-11-05 10:18:12 -080035 private final static Logger log = LoggerFactory.getLogger(FlowPusher.class);
36
37 // NOTE: Below are moved from FlowManager.
38 // TODO: Values copied from elsewhere (class LearningSwitch).
39 // The local copy should go away!
40 //
41 protected static final int OFMESSAGE_DAMPER_CAPACITY = 50000; // TODO: find sweet spot
42 protected static final int OFMESSAGE_DAMPER_TIMEOUT = 250; // ms
Naoki Shiota5c8d19f2013-11-05 15:52:38 -080043
44 protected static final long SLEEP_MILLI_SEC = 3;
45 protected static final int SLEEP_NANO_SEC = 0;
Naoki Shiota7d0cf272013-11-05 10:18:12 -080046
47 public static final short PRIORITY_DEFAULT = 100;
48 public static final short FLOWMOD_DEFAULT_IDLE_TIMEOUT = 0; // infinity
49 public static final short FLOWMOD_DEFAULT_HARD_TIMEOUT = 0; // infinite
50
51 public enum QueueState {
52 READY,
53 SUSPENDED,
54 }
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070055
Naoki Shiota7d0cf272013-11-05 10:18:12 -080056 private class SwitchQueue extends ArrayDeque<OFMessage> {
57 QueueState state;
58
59 // Max rate of sending message (bytes/sec). 0 implies no limitation.
Naoki Shiota8ee48d52013-11-11 15:51:17 -080060 long max_rate = 0; // 0 indicates no limitation
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070061 long last_sent_time = 0;
62 long last_sent_size = 0;
Naoki Shiota7d0cf272013-11-05 10:18:12 -080063
64 /**
65 * Check if sending rate is within the rate
66 * @param current Current time
67 * @return true if within the rate
68 */
69 boolean isSendable(long current) {
Naoki Shiota8ee48d52013-11-11 15:51:17 -080070 if (max_rate == 0) {
71 // no limitation
72 return true;
73 }
74
Naoki Shiota7d0cf272013-11-05 10:18:12 -080075 long rate = last_sent_size / (current - last_sent_time);
76
77 if (rate < max_rate) {
78 return true;
79 } else {
80 return false;
81 }
82 }
83
84 void updateRate(long current, OFMessage msg) {
85 last_sent_time = current;
86 last_sent_size = msg.getLengthU();
87 }
88
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -070089 }
Naoki Shiota7d0cf272013-11-05 10:18:12 -080090
91 private Map<IOFSwitch,SwitchQueue> queues
92 = new HashMap<IOFSwitch,SwitchQueue>();
93
94 private OFMessageDamper messageDamper;
Naoki Shiotacf1acca2013-10-31 11:40:32 -070095
Naoki Shiota7d0cf272013-11-05 10:18:12 -080096 private FloodlightContext context = null;
97 private BasicFactory factory = null;
98 private Thread thread = null;
99
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800100 private boolean isStopped = false;
101 private boolean isMsgAdded = false;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800102
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700103 private class FlowPusherProcess implements Runnable {
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800104
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700105 @Override
106 public void run() {
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800107 log.debug("Begin Flow Pusher Process");
Naoki Shiotac2a699a2013-10-31 15:36:01 -0700108
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700109 while (true) {
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800110 Set< Map.Entry<IOFSwitch,SwitchQueue> > entries;
111 synchronized (queues) {
112 entries = queues.entrySet();
113 }
114
115 // Set taint flag to false at this moment.
116 isMsgAdded = false;
117
118 for (Map.Entry<IOFSwitch,SwitchQueue> entry : entries) {
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800119 IOFSwitch sw = entry.getKey();
120 SwitchQueue queue = entry.getValue();
121
Naoki Shiotac2a699a2013-10-31 15:36:01 -0700122 // Skip if queue is suspended
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800123 if (sw == null || queue == null ||
124 queue.state != QueueState.READY) {
Naoki Shiotac2a699a2013-10-31 15:36:01 -0700125 continue;
126 }
127
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800128 // check sending rate and determine it to be sent or not
129 long current_time = System.nanoTime();
130
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800131 synchronized (queue) {
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800132 if (queue.isSendable(current_time)) {
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800133 while (! queue.isEmpty()) {
134 OFMessage msg = queue.poll();
135
136 // if need to send, call IOFSwitch#write()
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800137 try {
138 messageDamper.write(sw, msg, context);
139 queue.updateRate(current_time, msg);
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800140 log.debug("Pusher sends message : {}", msg);
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800141 } catch (IOException e) {
142 // TODO Auto-generated catch block
143 e.printStackTrace();
144 }
145 }
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700146 }
147 }
148 }
149
150 // sleep while all queues are empty
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800151 while (! isMsgAdded) {
152 if (isStopped) {
153 log.debug("Pusher Process finished.");
154 return;
155 }
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800156
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800157 try {
158 Thread.sleep(SLEEP_MILLI_SEC, SLEEP_NANO_SEC);
159 } catch (InterruptedException e) {
160 // TODO Auto-generated catch block
161 e.printStackTrace();
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800162 log.error("Thread.sleep failed");
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800163 }
164 }
165
166 log.debug("Exit sleep loop.");
167
168 if (isStopped) {
169 log.debug("Pusher Process finished.");
170 return;
171 }
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800172
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700173 }
174 }
175 }
176
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800177 public void init(FloodlightContext context, BasicFactory factory, OFMessageDamper damper) {
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700178 this.context = context;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800179 this.factory = factory;
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800180
181 if (damper != null) {
182 messageDamper = damper;
183 } else {
184 // use default value
185 messageDamper = new OFMessageDamper(OFMESSAGE_DAMPER_CAPACITY,
186 EnumSet.of(OFType.FLOW_MOD),
187 OFMESSAGE_DAMPER_TIMEOUT);
188 }
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700189 }
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800190 /**
191 * Begin processing queue.
192 */
193 public void start() {
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800194 if (factory == null) {
195 log.error("FlowPusher not yet initialized.");
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800196 return;
197 }
198
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700199 thread = new Thread(new FlowPusherProcess());
200 thread.start();
201 }
202
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800203 /**
204 * Suspend processing a queue related to given switch.
205 * @param sw
206 */
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800207 public boolean suspend(IOFSwitch sw) {
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800208 SwitchQueue queue = getQueue(sw);
209
210 if (queue == null) {
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800211 return false;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800212 }
213
214 synchronized (queue) {
215 if (queue.state == QueueState.READY) {
216 queue.state = QueueState.SUSPENDED;
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800217 return true;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800218 }
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800219 return false;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800220 }
221 }
222
223 /**
224 * Resume processing a queue related to given switch.
225 */
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800226 public boolean resume(IOFSwitch sw) {
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800227 SwitchQueue queue = getQueue(sw);
228
229 if (queue == null) {
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800230 return false;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800231 }
232
233 synchronized (queue) {
234 if (queue.state == QueueState.SUSPENDED) {
235 queue.state = QueueState.READY;
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800236 return true;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800237 }
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800238 return false;
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800239 }
240 }
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800241
242 public boolean isSuspended(IOFSwitch sw) {
243 SwitchQueue queue = getQueue(sw);
244
245 if (queue == null) {
246 // TODO Is true suitable for this case?
247 return true;
248 }
249
250 return (queue.state == QueueState.SUSPENDED);
251 }
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800252
253 /**
254 * End processing queue and exit thread.
255 */
256 public void stop() {
Naoki Shiotac2a699a2013-10-31 15:36:01 -0700257 if (thread != null && thread.isAlive()) {
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800258 isStopped = true;
259 }
260 }
261
262 public void setRate(IOFSwitch sw, long rate) {
263 SwitchQueue queue = getQueue(sw);
264 if (queue == null) {
265 return;
266 }
267
268 if (rate > 0) {
269 queue.max_rate = rate;
Naoki Shiotac2a699a2013-10-31 15:36:01 -0700270 }
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700271 }
Naoki Shiotac2a699a2013-10-31 15:36:01 -0700272
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800273 /**
274 * Add OFMessage to the queue related to given switch.
275 * @param sw
276 * @param msg
277 */
278 public boolean send(IOFSwitch sw, OFMessage msg) {
279 SwitchQueue queue = getQueue(sw);
280 if (queue == null) {
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800281 queue = new SwitchQueue();
282 queue.state = QueueState.READY;
283 synchronized (queues) {
284 queues.put(sw, queue);
285 }
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800286 }
287
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800288 log.debug("Message is pushed : {}", msg);
289
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800290 synchronized (queue) {
291 queue.add(msg);
292 }
293
Naoki Shiota5c8d19f2013-11-05 15:52:38 -0800294 isMsgAdded = true;
295
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800296 return true;
297 }
298
299 /**
300 * Create OFMessage from given flow information and add it to the queue.
301 * @param sw
302 * @param flowObj
303 * @param flowEntryObj
304 * @return
305 */
306 public boolean send(IOFSwitch sw, IFlowPath flowObj, IFlowEntry flowEntryObj) {
Naoki Shiota8ee48d52013-11-11 15:51:17 -0800307 log.debug("sending : {}, {}", sw, flowObj);
Naoki Shiota7d0cf272013-11-05 10:18:12 -0800308 String flowEntryIdStr = flowEntryObj.getFlowEntryId();
309 if (flowEntryIdStr == null)
310 return false;
311 FlowEntryId flowEntryId = new FlowEntryId(flowEntryIdStr);
312 String userState = flowEntryObj.getUserState();
313 if (userState == null)
314 return false;
315
316 //
317 // Create the Open Flow Flow Modification Entry to push
318 //
319 OFFlowMod fm = (OFFlowMod)factory.getMessage(OFType.FLOW_MOD);
320 long cookie = flowEntryId.value();
321
322 short flowModCommand = OFFlowMod.OFPFC_ADD;
323 if (userState.equals("FE_USER_ADD")) {
324 flowModCommand = OFFlowMod.OFPFC_ADD;
325 } else if (userState.equals("FE_USER_MODIFY")) {
326 flowModCommand = OFFlowMod.OFPFC_MODIFY_STRICT;
327 } else if (userState.equals("FE_USER_DELETE")) {
328 flowModCommand = OFFlowMod.OFPFC_DELETE_STRICT;
329 } else {
330 // Unknown user state. Ignore the entry
331 log.debug("Flow Entry ignored (FlowEntryId = {}): unknown user state {}",
332 flowEntryId.toString(), userState);
333 return false;
334 }
335
336 //
337 // Fetch the match conditions.
338 //
339 // NOTE: The Flow matching conditions common for all Flow Entries are
340 // used ONLY if a Flow Entry does NOT have the corresponding matching
341 // condition set.
342 //
343 OFMatch match = new OFMatch();
344 match.setWildcards(OFMatch.OFPFW_ALL);
345
346 // Match the Incoming Port
347 Short matchInPort = flowEntryObj.getMatchInPort();
348 if (matchInPort != null) {
349 match.setInputPort(matchInPort);
350 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_IN_PORT);
351 }
352
353 // Match the Source MAC address
354 String matchSrcMac = flowEntryObj.getMatchSrcMac();
355 if (matchSrcMac == null)
356 matchSrcMac = flowObj.getMatchSrcMac();
357 if (matchSrcMac != null) {
358 match.setDataLayerSource(matchSrcMac);
359 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
360 }
361
362 // Match the Destination MAC address
363 String matchDstMac = flowEntryObj.getMatchDstMac();
364 if (matchDstMac == null)
365 matchDstMac = flowObj.getMatchDstMac();
366 if (matchDstMac != null) {
367 match.setDataLayerDestination(matchDstMac);
368 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
369 }
370
371 // Match the Ethernet Frame Type
372 Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
373 if (matchEthernetFrameType == null)
374 matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
375 if (matchEthernetFrameType != null) {
376 match.setDataLayerType(matchEthernetFrameType);
377 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
378 }
379
380 // Match the VLAN ID
381 Short matchVlanId = flowEntryObj.getMatchVlanId();
382 if (matchVlanId == null)
383 matchVlanId = flowObj.getMatchVlanId();
384 if (matchVlanId != null) {
385 match.setDataLayerVirtualLan(matchVlanId);
386 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN);
387 }
388
389 // Match the VLAN priority
390 Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
391 if (matchVlanPriority == null)
392 matchVlanPriority = flowObj.getMatchVlanPriority();
393 if (matchVlanPriority != null) {
394 match.setDataLayerVirtualLanPriorityCodePoint(matchVlanPriority);
395 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN_PCP);
396 }
397
398 // Match the Source IPv4 Network prefix
399 String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
400 if (matchSrcIPv4Net == null)
401 matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
402 if (matchSrcIPv4Net != null) {
403 match.setFromCIDR(matchSrcIPv4Net, OFMatch.STR_NW_SRC);
404 }
405
406 // Match the Destination IPv4 Network prefix
407 String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
408 if (matchDstIPv4Net == null)
409 matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
410 if (matchDstIPv4Net != null) {
411 match.setFromCIDR(matchDstIPv4Net, OFMatch.STR_NW_DST);
412 }
413
414 // Match the IP protocol
415 Byte matchIpProto = flowEntryObj.getMatchIpProto();
416 if (matchIpProto == null)
417 matchIpProto = flowObj.getMatchIpProto();
418 if (matchIpProto != null) {
419 match.setNetworkProtocol(matchIpProto);
420 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_PROTO);
421 }
422
423 // Match the IP ToS (DSCP field, 6 bits)
424 Byte matchIpToS = flowEntryObj.getMatchIpToS();
425 if (matchIpToS == null)
426 matchIpToS = flowObj.getMatchIpToS();
427 if (matchIpToS != null) {
428 match.setNetworkTypeOfService(matchIpToS);
429 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_TOS);
430 }
431
432 // Match the Source TCP/UDP port
433 Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
434 if (matchSrcTcpUdpPort == null)
435 matchSrcTcpUdpPort = flowObj.getMatchSrcTcpUdpPort();
436 if (matchSrcTcpUdpPort != null) {
437 match.setTransportSource(matchSrcTcpUdpPort);
438 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
439 }
440
441 // Match the Destination TCP/UDP port
442 Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
443 if (matchDstTcpUdpPort == null)
444 matchDstTcpUdpPort = flowObj.getMatchDstTcpUdpPort();
445 if (matchDstTcpUdpPort != null) {
446 match.setTransportDestination(matchDstTcpUdpPort);
447 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_DST);
448 }
449
450 //
451 // Fetch the actions
452 //
453 Short actionOutputPort = null;
454 List<OFAction> openFlowActions = new ArrayList<OFAction>();
455 int actionsLen = 0;
456 FlowEntryActions flowEntryActions = null;
457 String actionsStr = flowEntryObj.getActions();
458 if (actionsStr != null)
459 flowEntryActions = new FlowEntryActions(actionsStr);
460 else
461 flowEntryActions = new FlowEntryActions();
462 for (FlowEntryAction action : flowEntryActions.actions()) {
463 ActionOutput actionOutput = action.actionOutput();
464 ActionSetVlanId actionSetVlanId = action.actionSetVlanId();
465 ActionSetVlanPriority actionSetVlanPriority = action.actionSetVlanPriority();
466 ActionStripVlan actionStripVlan = action.actionStripVlan();
467 ActionSetEthernetAddr actionSetEthernetSrcAddr = action.actionSetEthernetSrcAddr();
468 ActionSetEthernetAddr actionSetEthernetDstAddr = action.actionSetEthernetDstAddr();
469 ActionSetIPv4Addr actionSetIPv4SrcAddr = action.actionSetIPv4SrcAddr();
470 ActionSetIPv4Addr actionSetIPv4DstAddr = action.actionSetIPv4DstAddr();
471 ActionSetIpToS actionSetIpToS = action.actionSetIpToS();
472 ActionSetTcpUdpPort actionSetTcpUdpSrcPort = action.actionSetTcpUdpSrcPort();
473 ActionSetTcpUdpPort actionSetTcpUdpDstPort = action.actionSetTcpUdpDstPort();
474 ActionEnqueue actionEnqueue = action.actionEnqueue();
475
476 if (actionOutput != null) {
477 actionOutputPort = actionOutput.port().value();
478 // XXX: The max length is hard-coded for now
479 OFActionOutput ofa =
480 new OFActionOutput(actionOutput.port().value(),
481 (short)0xffff);
482 openFlowActions.add(ofa);
483 actionsLen += ofa.getLength();
484 }
485
486 if (actionSetVlanId != null) {
487 OFActionVirtualLanIdentifier ofa =
488 new OFActionVirtualLanIdentifier(actionSetVlanId.vlanId());
489 openFlowActions.add(ofa);
490 actionsLen += ofa.getLength();
491 }
492
493 if (actionSetVlanPriority != null) {
494 OFActionVirtualLanPriorityCodePoint ofa =
495 new OFActionVirtualLanPriorityCodePoint(actionSetVlanPriority.vlanPriority());
496 openFlowActions.add(ofa);
497 actionsLen += ofa.getLength();
498 }
499
500 if (actionStripVlan != null) {
501 if (actionStripVlan.stripVlan() == true) {
502 OFActionStripVirtualLan ofa = new OFActionStripVirtualLan();
503 openFlowActions.add(ofa);
504 actionsLen += ofa.getLength();
505 }
506 }
507
508 if (actionSetEthernetSrcAddr != null) {
509 OFActionDataLayerSource ofa =
510 new OFActionDataLayerSource(actionSetEthernetSrcAddr.addr().toBytes());
511 openFlowActions.add(ofa);
512 actionsLen += ofa.getLength();
513 }
514
515 if (actionSetEthernetDstAddr != null) {
516 OFActionDataLayerDestination ofa =
517 new OFActionDataLayerDestination(actionSetEthernetDstAddr.addr().toBytes());
518 openFlowActions.add(ofa);
519 actionsLen += ofa.getLength();
520 }
521
522 if (actionSetIPv4SrcAddr != null) {
523 OFActionNetworkLayerSource ofa =
524 new OFActionNetworkLayerSource(actionSetIPv4SrcAddr.addr().value());
525 openFlowActions.add(ofa);
526 actionsLen += ofa.getLength();
527 }
528
529 if (actionSetIPv4DstAddr != null) {
530 OFActionNetworkLayerDestination ofa =
531 new OFActionNetworkLayerDestination(actionSetIPv4DstAddr.addr().value());
532 openFlowActions.add(ofa);
533 actionsLen += ofa.getLength();
534 }
535
536 if (actionSetIpToS != null) {
537 OFActionNetworkTypeOfService ofa =
538 new OFActionNetworkTypeOfService(actionSetIpToS.ipToS());
539 openFlowActions.add(ofa);
540 actionsLen += ofa.getLength();
541 }
542
543 if (actionSetTcpUdpSrcPort != null) {
544 OFActionTransportLayerSource ofa =
545 new OFActionTransportLayerSource(actionSetTcpUdpSrcPort.port());
546 openFlowActions.add(ofa);
547 actionsLen += ofa.getLength();
548 }
549
550 if (actionSetTcpUdpDstPort != null) {
551 OFActionTransportLayerDestination ofa =
552 new OFActionTransportLayerDestination(actionSetTcpUdpDstPort.port());
553 openFlowActions.add(ofa);
554 actionsLen += ofa.getLength();
555 }
556
557 if (actionEnqueue != null) {
558 OFActionEnqueue ofa =
559 new OFActionEnqueue(actionEnqueue.port().value(),
560 actionEnqueue.queueId());
561 openFlowActions.add(ofa);
562 actionsLen += ofa.getLength();
563 }
564 }
565
566 fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
567 .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
568 .setPriority(PRIORITY_DEFAULT)
569 .setBufferId(OFPacketOut.BUFFER_ID_NONE)
570 .setCookie(cookie)
571 .setCommand(flowModCommand)
572 .setMatch(match)
573 .setActions(openFlowActions)
574 .setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLen);
575 fm.setOutPort(OFPort.OFPP_NONE.getValue());
576 if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
577 (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
578 if (actionOutputPort != null)
579 fm.setOutPort(actionOutputPort);
580 }
581
582 //
583 // TODO: Set the following flag
584 // fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
585 // See method ForwardingBase::pushRoute()
586 //
587
588 //
589 // Write the message to the switch
590 //
591 log.debug("MEASUREMENT: Installing flow entry " + userState +
592 " into switch DPID: " +
593 sw.getStringId() +
594 " flowEntryId: " + flowEntryId.toString() +
595 " srcMac: " + matchSrcMac + " dstMac: " + matchDstMac +
596 " inPort: " + matchInPort + " outPort: " + actionOutputPort
597 );
598 send(sw,fm);
599 //
600 // TODO: We should use the OpenFlow Barrier mechanism
601 // to check for errors, and update the SwitchState
602 // for a flow entry after the Barrier message is
603 // is received.
604 //
605 flowEntryObj.setSwitchState("FE_SWITCH_UPDATED");
606
607 return true;
608 }
609
610 private SwitchQueue getQueue(IOFSwitch sw) {
611 if (sw == null) {
612 return null;
613 }
614
615 return queues.get(sw);
616 }
Naoki Shiotaed4eb5e2013-10-31 10:55:32 -0700617}