blob: 3b6409661590864c3d0ec7205076c76b7f529f61 [file] [log] [blame]
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -07001package net.onrc.onos.ofcontroller.flowmanager;
2
3import java.io.IOException;
4import java.util.ArrayList;
5import java.util.List;
6
7import net.floodlightcontroller.core.IOFSwitch;
8import net.floodlightcontroller.util.MACAddress;
9import net.floodlightcontroller.util.OFMessageDamper;
10
11import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
12import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
13import net.onrc.onos.ofcontroller.util.*;
14import net.onrc.onos.ofcontroller.util.FlowEntryAction.*;
15
16import org.openflow.protocol.OFFlowMod;
17import org.openflow.protocol.OFMatch;
18import org.openflow.protocol.OFPacketOut;
19import org.openflow.protocol.OFPort;
20import org.openflow.protocol.OFType;
21import org.openflow.protocol.action.*;
22import org.openflow.protocol.factory.BasicFactory;
23import org.slf4j.Logger;
24import org.slf4j.LoggerFactory;
25
26/**
27 * Class for performing Flow-related operations on the Switch.
28 */
29class FlowSwitchOperation {
Yuta HIGUCHI6ac8d182013-10-22 15:24:56 -070030 private final static Logger log = LoggerFactory.getLogger(FlowSwitchOperation.class);
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -070031 //
32 // TODO: Values copied from elsewhere (class LearningSwitch).
33 // The local copy should go away!
34 //
35 public static final short PRIORITY_DEFAULT = 100;
36 public static final short FLOWMOD_DEFAULT_IDLE_TIMEOUT = 0; // infinity
37 public static final short FLOWMOD_DEFAULT_HARD_TIMEOUT = 0; // infinite
38
39 /**
40 * Install a Flow Entry on a switch.
41 *
42 * @param messageFactory the OpenFlow message factory to use.
43 * @maram messageDamper the OpenFlow message damper to use.
44 * @param mySwitch the switch to install the Flow Entry into.
45 * @param flowObj the flow path object for the flow entry to install.
46 * @param flowEntryObj the flow entry object to install.
47 * @return true on success, otherwise false.
48 */
49 static boolean installFlowEntry(BasicFactory messageFactory,
50 OFMessageDamper messageDamper,
51 IOFSwitch mySwitch, IFlowPath flowObj,
52 IFlowEntry flowEntryObj) {
53 String flowEntryIdStr = flowEntryObj.getFlowEntryId();
54 if (flowEntryIdStr == null)
55 return false;
56 FlowEntryId flowEntryId = new FlowEntryId(flowEntryIdStr);
57 String userState = flowEntryObj.getUserState();
58 if (userState == null)
59 return false;
60
61 //
62 // Create the Open Flow Flow Modification Entry to push
63 //
64 OFFlowMod fm = (OFFlowMod)messageFactory.getMessage(OFType.FLOW_MOD);
65 long cookie = flowEntryId.value();
66
67 short flowModCommand = OFFlowMod.OFPFC_ADD;
68 if (userState.equals("FE_USER_ADD")) {
69 flowModCommand = OFFlowMod.OFPFC_ADD;
70 } else if (userState.equals("FE_USER_MODIFY")) {
71 flowModCommand = OFFlowMod.OFPFC_MODIFY_STRICT;
72 } else if (userState.equals("FE_USER_DELETE")) {
73 flowModCommand = OFFlowMod.OFPFC_DELETE_STRICT;
74 } else {
75 // Unknown user state. Ignore the entry
76 log.debug("Flow Entry ignored (FlowEntryId = {}): unknown user state {}",
77 flowEntryId.toString(), userState);
78 return false;
79 }
80
81 //
82 // Fetch the match conditions.
83 //
84 // NOTE: The Flow matching conditions common for all Flow Entries are
85 // used ONLY if a Flow Entry does NOT have the corresponding matching
86 // condition set.
87 //
88 OFMatch match = new OFMatch();
89 match.setWildcards(OFMatch.OFPFW_ALL);
90
91 // Match the Incoming Port
92 Short matchInPort = flowEntryObj.getMatchInPort();
93 if (matchInPort != null) {
94 match.setInputPort(matchInPort);
95 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_IN_PORT);
96 }
97
98 // Match the Source MAC address
99 String matchSrcMac = flowEntryObj.getMatchSrcMac();
100 if (matchSrcMac == null)
101 matchSrcMac = flowObj.getMatchSrcMac();
102 if (matchSrcMac != null) {
103 match.setDataLayerSource(matchSrcMac);
104 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
105 }
106
107 // Match the Destination MAC address
108 String matchDstMac = flowEntryObj.getMatchDstMac();
109 if (matchDstMac == null)
110 matchDstMac = flowObj.getMatchDstMac();
111 if (matchDstMac != null) {
112 match.setDataLayerDestination(matchDstMac);
113 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
114 }
115
116 // Match the Ethernet Frame Type
117 Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
118 if (matchEthernetFrameType == null)
119 matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
120 if (matchEthernetFrameType != null) {
121 match.setDataLayerType(matchEthernetFrameType);
122 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
123 }
124
125 // Match the VLAN ID
126 Short matchVlanId = flowEntryObj.getMatchVlanId();
127 if (matchVlanId == null)
128 matchVlanId = flowObj.getMatchVlanId();
129 if (matchVlanId != null) {
130 match.setDataLayerVirtualLan(matchVlanId);
131 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN);
132 }
133
134 // Match the VLAN priority
135 Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
136 if (matchVlanPriority == null)
137 matchVlanPriority = flowObj.getMatchVlanPriority();
138 if (matchVlanPriority != null) {
139 match.setDataLayerVirtualLanPriorityCodePoint(matchVlanPriority);
140 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN_PCP);
141 }
142
143 // Match the Source IPv4 Network prefix
144 String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
145 if (matchSrcIPv4Net == null)
146 matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
147 if (matchSrcIPv4Net != null) {
148 match.setFromCIDR(matchSrcIPv4Net, OFMatch.STR_NW_SRC);
149 }
150
151 // Natch the Destination IPv4 Network prefix
152 String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
153 if (matchDstIPv4Net == null)
154 matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
155 if (matchDstIPv4Net != null) {
156 match.setFromCIDR(matchDstIPv4Net, OFMatch.STR_NW_DST);
157 }
158
159 // Match the IP protocol
160 Byte matchIpProto = flowEntryObj.getMatchIpProto();
161 if (matchIpProto == null)
162 matchIpProto = flowObj.getMatchIpProto();
163 if (matchIpProto != null) {
164 match.setNetworkProtocol(matchIpProto);
165 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_PROTO);
166 }
167
168 // Match the IP ToS (DSCP field, 6 bits)
169 Byte matchIpToS = flowEntryObj.getMatchIpToS();
170 if (matchIpToS == null)
171 matchIpToS = flowObj.getMatchIpToS();
172 if (matchIpToS != null) {
173 match.setNetworkTypeOfService(matchIpToS);
174 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_TOS);
175 }
176
177 // Match the Source TCP/UDP port
178 Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
179 if (matchSrcTcpUdpPort == null)
180 matchSrcTcpUdpPort = flowObj.getMatchSrcTcpUdpPort();
181 if (matchSrcTcpUdpPort != null) {
182 match.setTransportSource(matchSrcTcpUdpPort);
183 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
184 }
185
186 // Match the Destination TCP/UDP port
187 Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
188 if (matchDstTcpUdpPort == null)
189 matchDstTcpUdpPort = flowObj.getMatchDstTcpUdpPort();
190 if (matchDstTcpUdpPort != null) {
191 match.setTransportDestination(matchDstTcpUdpPort);
192 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_DST);
193 }
194
195 //
196 // Fetch the actions
197 //
198 Short actionOutputPort = null;
199 List<OFAction> openFlowActions = new ArrayList<OFAction>();
200 int actionsLen = 0;
201 FlowEntryActions flowEntryActions = null;
202 String actionsStr = flowEntryObj.getActions();
203 if (actionsStr != null)
204 flowEntryActions = new FlowEntryActions(actionsStr);
205 for (FlowEntryAction action : flowEntryActions.actions()) {
206 ActionOutput actionOutput = action.actionOutput();
207 ActionSetVlanId actionSetVlanId = action.actionSetVlanId();
208 ActionSetVlanPriority actionSetVlanPriority = action.actionSetVlanPriority();
209 ActionStripVlan actionStripVlan = action.actionStripVlan();
210 ActionSetEthernetAddr actionSetEthernetSrcAddr = action.actionSetEthernetSrcAddr();
211 ActionSetEthernetAddr actionSetEthernetDstAddr = action.actionSetEthernetDstAddr();
212 ActionSetIPv4Addr actionSetIPv4SrcAddr = action.actionSetIPv4SrcAddr();
213 ActionSetIPv4Addr actionSetIPv4DstAddr = action.actionSetIPv4DstAddr();
214 ActionSetIpToS actionSetIpToS = action.actionSetIpToS();
215 ActionSetTcpUdpPort actionSetTcpUdpSrcPort = action.actionSetTcpUdpSrcPort();
216 ActionSetTcpUdpPort actionSetTcpUdpDstPort = action.actionSetTcpUdpDstPort();
217 ActionEnqueue actionEnqueue = action.actionEnqueue();
218
219 if (actionOutput != null) {
220 actionOutputPort = actionOutput.port().value();
221 // XXX: The max length is hard-coded for now
222 OFActionOutput ofa =
223 new OFActionOutput(actionOutput.port().value(),
224 (short)0xffff);
225 openFlowActions.add(ofa);
226 actionsLen += ofa.getLength();
227 }
228
229 if (actionSetVlanId != null) {
230 OFActionVirtualLanIdentifier ofa =
231 new OFActionVirtualLanIdentifier(actionSetVlanId.vlanId());
232 openFlowActions.add(ofa);
233 actionsLen += ofa.getLength();
234 }
235
236 if (actionSetVlanPriority != null) {
237 OFActionVirtualLanPriorityCodePoint ofa =
238 new OFActionVirtualLanPriorityCodePoint(actionSetVlanPriority.vlanPriority());
239 openFlowActions.add(ofa);
240 actionsLen += ofa.getLength();
241 }
242
243 if (actionStripVlan != null) {
244 if (actionStripVlan.stripVlan() == true) {
245 OFActionStripVirtualLan ofa = new OFActionStripVirtualLan();
246 openFlowActions.add(ofa);
247 actionsLen += ofa.getLength();
248 }
249 }
250
251 if (actionSetEthernetSrcAddr != null) {
252 OFActionDataLayerSource ofa =
253 new OFActionDataLayerSource(actionSetEthernetSrcAddr.addr().toBytes());
254 openFlowActions.add(ofa);
255 actionsLen += ofa.getLength();
256 }
257
258 if (actionSetEthernetDstAddr != null) {
259 OFActionDataLayerDestination ofa =
260 new OFActionDataLayerDestination(actionSetEthernetDstAddr.addr().toBytes());
261 openFlowActions.add(ofa);
262 actionsLen += ofa.getLength();
263 }
264
265 if (actionSetIPv4SrcAddr != null) {
266 OFActionNetworkLayerSource ofa =
267 new OFActionNetworkLayerSource(actionSetIPv4SrcAddr.addr().value());
268 openFlowActions.add(ofa);
269 actionsLen += ofa.getLength();
270 }
271
272 if (actionSetIPv4DstAddr != null) {
273 OFActionNetworkLayerDestination ofa =
274 new OFActionNetworkLayerDestination(actionSetIPv4DstAddr.addr().value());
275 openFlowActions.add(ofa);
276 actionsLen += ofa.getLength();
277 }
278
279 if (actionSetIpToS != null) {
280 OFActionNetworkTypeOfService ofa =
281 new OFActionNetworkTypeOfService(actionSetIpToS.ipToS());
282 openFlowActions.add(ofa);
283 actionsLen += ofa.getLength();
284 }
285
286 if (actionSetTcpUdpSrcPort != null) {
287 OFActionTransportLayerSource ofa =
288 new OFActionTransportLayerSource(actionSetTcpUdpSrcPort.port());
289 openFlowActions.add(ofa);
290 actionsLen += ofa.getLength();
291 }
292
293 if (actionSetTcpUdpDstPort != null) {
294 OFActionTransportLayerDestination ofa =
295 new OFActionTransportLayerDestination(actionSetTcpUdpDstPort.port());
296 openFlowActions.add(ofa);
297 actionsLen += ofa.getLength();
298 }
299
300 if (actionEnqueue != null) {
301 OFActionEnqueue ofa =
302 new OFActionEnqueue(actionEnqueue.port().value(),
303 actionEnqueue.queueId());
304 openFlowActions.add(ofa);
305 actionsLen += ofa.getLength();
306 }
307 }
308
309 fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
310 .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
311 .setPriority(PRIORITY_DEFAULT)
312 .setBufferId(OFPacketOut.BUFFER_ID_NONE)
313 .setCookie(cookie)
314 .setCommand(flowModCommand)
315 .setMatch(match)
316 .setActions(openFlowActions)
317 .setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLen);
318 fm.setOutPort(OFPort.OFPP_NONE.getValue());
319 if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
320 (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
321 if (actionOutputPort != null)
322 fm.setOutPort(actionOutputPort);
323 }
324
325 //
326 // TODO: Set the following flag
327 // fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
328 // See method ForwardingBase::pushRoute()
329 //
330
331 //
332 // Write the message to the switch
333 //
334 log.debug("MEASUREMENT: Installing flow entry " + userState +
335 " into switch DPID: " +
336 mySwitch.getStringId() +
337 " flowEntryId: " + flowEntryId.toString() +
338 " srcMac: " + matchSrcMac + " dstMac: " + matchDstMac +
339 " inPort: " + matchInPort + " outPort: " + actionOutputPort
340 );
341 try {
342 messageDamper.write(mySwitch, fm, null);
343 mySwitch.flush();
344 //
345 // TODO: We should use the OpenFlow Barrier mechanism
346 // to check for errors, and update the SwitchState
347 // for a flow entry after the Barrier message is
348 // is received.
349 //
350 flowEntryObj.setSwitchState("FE_SWITCH_UPDATED");
351 } catch (IOException e) {
352 log.error("Failure writing flow mod from network map", e);
353 return false;
354 }
355
356 return true;
357 }
358
359 /**
360 * Install a Flow Entry on a switch.
361 *
362 * @param messageFactory the OpenFlow message factory to use.
363 * @maram messageDamper the OpenFlow message damper to use.
364 * @param mySwitch the switch to install the Flow Entry into.
365 * @param flowPath the flow path for the flow entry to install.
366 * @param flowEntry the flow entry to install.
367 * @return true on success, otherwise false.
368 */
369 static boolean installFlowEntry(BasicFactory messageFactory,
370 OFMessageDamper messageDamper,
371 IOFSwitch mySwitch, FlowPath flowPath,
372 FlowEntry flowEntry) {
373 //
374 // Create the OpenFlow Flow Modification Entry to push
375 //
376 OFFlowMod fm = (OFFlowMod)messageFactory.getMessage(OFType.FLOW_MOD);
377 long cookie = flowEntry.flowEntryId().value();
378
379 short flowModCommand = OFFlowMod.OFPFC_ADD;
380 if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_ADD) {
381 flowModCommand = OFFlowMod.OFPFC_ADD;
382 } else if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_MODIFY) {
383 flowModCommand = OFFlowMod.OFPFC_MODIFY_STRICT;
384 } else if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_DELETE) {
385 flowModCommand = OFFlowMod.OFPFC_DELETE_STRICT;
386 } else {
387 // Unknown user state. Ignore the entry
388 log.debug("Flow Entry ignored (FlowEntryId = {}): unknown user state {}",
389 flowEntry.flowEntryId().toString(),
390 flowEntry.flowEntryUserState());
391 return false;
392 }
393
394 //
395 // Fetch the match conditions.
396 //
397 // NOTE: The Flow matching conditions common for all Flow Entries are
398 // used ONLY if a Flow Entry does NOT have the corresponding matching
399 // condition set.
400 //
401 OFMatch match = new OFMatch();
402 match.setWildcards(OFMatch.OFPFW_ALL);
403 FlowEntryMatch flowPathMatch = flowPath.flowEntryMatch();
404 FlowEntryMatch flowEntryMatch = flowEntry.flowEntryMatch();
405
406 // Match the Incoming Port
407 Port matchInPort = flowEntryMatch.inPort();
408 if (matchInPort != null) {
409 match.setInputPort(matchInPort.value());
410 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_IN_PORT);
411 }
412
413 // Match the Source MAC address
414 MACAddress matchSrcMac = flowEntryMatch.srcMac();
415 if ((matchSrcMac == null) && (flowPathMatch != null)) {
416 matchSrcMac = flowPathMatch.srcMac();
417 }
418 if (matchSrcMac != null) {
419 match.setDataLayerSource(matchSrcMac.toString());
420 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
421 }
422
423 // Match the Destination MAC address
424 MACAddress matchDstMac = flowEntryMatch.dstMac();
425 if ((matchDstMac == null) && (flowPathMatch != null)) {
426 matchDstMac = flowPathMatch.dstMac();
427 }
428 if (matchDstMac != null) {
429 match.setDataLayerDestination(matchDstMac.toString());
430 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
431 }
432
433 // Match the Ethernet Frame Type
434 Short matchEthernetFrameType = flowEntryMatch.ethernetFrameType();
435 if ((matchEthernetFrameType == null) && (flowPathMatch != null)) {
436 matchEthernetFrameType = flowPathMatch.ethernetFrameType();
437 }
438 if (matchEthernetFrameType != null) {
439 match.setDataLayerType(matchEthernetFrameType);
440 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
441 }
442
443 // Match the VLAN ID
444 Short matchVlanId = flowEntryMatch.vlanId();
445 if ((matchVlanId == null) && (flowPathMatch != null)) {
446 matchVlanId = flowPathMatch.vlanId();
447 }
448 if (matchVlanId != null) {
449 match.setDataLayerVirtualLan(matchVlanId);
450 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN);
451 }
452
453 // Match the VLAN priority
454 Byte matchVlanPriority = flowEntryMatch.vlanPriority();
455 if ((matchVlanPriority == null) && (flowPathMatch != null)) {
456 matchVlanPriority = flowPathMatch.vlanPriority();
457 }
458 if (matchVlanPriority != null) {
459 match.setDataLayerVirtualLanPriorityCodePoint(matchVlanPriority);
460 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN_PCP);
461 }
462
463 // Match the Source IPv4 Network prefix
464 IPv4Net matchSrcIPv4Net = flowEntryMatch.srcIPv4Net();
465 if ((matchSrcIPv4Net == null) && (flowPathMatch != null)) {
466 matchSrcIPv4Net = flowPathMatch.srcIPv4Net();
467 }
468 if (matchSrcIPv4Net != null) {
469 match.setFromCIDR(matchSrcIPv4Net.toString(), OFMatch.STR_NW_SRC);
470 }
471
472 // Natch the Destination IPv4 Network prefix
473 IPv4Net matchDstIPv4Net = flowEntryMatch.dstIPv4Net();
474 if ((matchDstIPv4Net == null) && (flowPathMatch != null)) {
475 matchDstIPv4Net = flowPathMatch.dstIPv4Net();
476 }
477 if (matchDstIPv4Net != null) {
478 match.setFromCIDR(matchDstIPv4Net.toString(), OFMatch.STR_NW_DST);
479 }
480
481 // Match the IP protocol
482 Byte matchIpProto = flowEntryMatch.ipProto();
483 if ((matchIpProto == null) && (flowPathMatch != null)) {
484 matchIpProto = flowPathMatch.ipProto();
485 }
486 if (matchIpProto != null) {
487 match.setNetworkProtocol(matchIpProto);
488 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_PROTO);
489 }
490
491 // Match the IP ToS (DSCP field, 6 bits)
492 Byte matchIpToS = flowEntryMatch.ipToS();
493 if ((matchIpToS == null) && (flowPathMatch != null)) {
494 matchIpToS = flowPathMatch.ipToS();
495 }
496 if (matchIpToS != null) {
497 match.setNetworkTypeOfService(matchIpToS);
498 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_TOS);
499 }
500
501 // Match the Source TCP/UDP port
502 Short matchSrcTcpUdpPort = flowEntryMatch.srcTcpUdpPort();
503 if ((matchSrcTcpUdpPort == null) && (flowPathMatch != null)) {
504 matchSrcTcpUdpPort = flowPathMatch.srcTcpUdpPort();
505 }
506 if (matchSrcTcpUdpPort != null) {
507 match.setTransportSource(matchSrcTcpUdpPort);
508 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
509 }
510
511 // Match the Destination TCP/UDP port
512 Short matchDstTcpUdpPort = flowEntryMatch.dstTcpUdpPort();
513 if ((matchDstTcpUdpPort == null) && (flowPathMatch != null)) {
514 matchDstTcpUdpPort = flowPathMatch.dstTcpUdpPort();
515 }
516 if (matchDstTcpUdpPort != null) {
517 match.setTransportDestination(matchDstTcpUdpPort);
518 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_DST);
519 }
520
521 //
522 // Fetch the actions
523 //
524 Short actionOutputPort = null;
525 List<OFAction> openFlowActions = new ArrayList<OFAction>();
526 int actionsLen = 0;
527 FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
528 //
529 for (FlowEntryAction action : flowEntryActions.actions()) {
530 ActionOutput actionOutput = action.actionOutput();
531 ActionSetVlanId actionSetVlanId = action.actionSetVlanId();
532 ActionSetVlanPriority actionSetVlanPriority = action.actionSetVlanPriority();
533 ActionStripVlan actionStripVlan = action.actionStripVlan();
534 ActionSetEthernetAddr actionSetEthernetSrcAddr = action.actionSetEthernetSrcAddr();
535 ActionSetEthernetAddr actionSetEthernetDstAddr = action.actionSetEthernetDstAddr();
536 ActionSetIPv4Addr actionSetIPv4SrcAddr = action.actionSetIPv4SrcAddr();
537 ActionSetIPv4Addr actionSetIPv4DstAddr = action.actionSetIPv4DstAddr();
538 ActionSetIpToS actionSetIpToS = action.actionSetIpToS();
539 ActionSetTcpUdpPort actionSetTcpUdpSrcPort = action.actionSetTcpUdpSrcPort();
540 ActionSetTcpUdpPort actionSetTcpUdpDstPort = action.actionSetTcpUdpDstPort();
541 ActionEnqueue actionEnqueue = action.actionEnqueue();
542
543 if (actionOutput != null) {
544 actionOutputPort = actionOutput.port().value();
545 // XXX: The max length is hard-coded for now
546 OFActionOutput ofa =
547 new OFActionOutput(actionOutput.port().value(),
548 (short)0xffff);
549 openFlowActions.add(ofa);
550 actionsLen += ofa.getLength();
551 }
552
553 if (actionSetVlanId != null) {
554 OFActionVirtualLanIdentifier ofa =
555 new OFActionVirtualLanIdentifier(actionSetVlanId.vlanId());
556 openFlowActions.add(ofa);
557 actionsLen += ofa.getLength();
558 }
559
560 if (actionSetVlanPriority != null) {
561 OFActionVirtualLanPriorityCodePoint ofa =
562 new OFActionVirtualLanPriorityCodePoint(actionSetVlanPriority.vlanPriority());
563 openFlowActions.add(ofa);
564 actionsLen += ofa.getLength();
565 }
566
567 if (actionStripVlan != null) {
568 if (actionStripVlan.stripVlan() == true) {
569 OFActionStripVirtualLan ofa = new OFActionStripVirtualLan();
570 openFlowActions.add(ofa);
571 actionsLen += ofa.getLength();
572 }
573 }
574
575 if (actionSetEthernetSrcAddr != null) {
576 OFActionDataLayerSource ofa =
577 new OFActionDataLayerSource(actionSetEthernetSrcAddr.addr().toBytes());
578 openFlowActions.add(ofa);
579 actionsLen += ofa.getLength();
580 }
581
582 if (actionSetEthernetDstAddr != null) {
583 OFActionDataLayerDestination ofa =
584 new OFActionDataLayerDestination(actionSetEthernetDstAddr.addr().toBytes());
585 openFlowActions.add(ofa);
586 actionsLen += ofa.getLength();
587 }
588
589 if (actionSetIPv4SrcAddr != null) {
590 OFActionNetworkLayerSource ofa =
591 new OFActionNetworkLayerSource(actionSetIPv4SrcAddr.addr().value());
592 openFlowActions.add(ofa);
593 actionsLen += ofa.getLength();
594 }
595
596 if (actionSetIPv4DstAddr != null) {
597 OFActionNetworkLayerDestination ofa =
598 new OFActionNetworkLayerDestination(actionSetIPv4DstAddr.addr().value());
599 openFlowActions.add(ofa);
600 actionsLen += ofa.getLength();
601 }
602
603 if (actionSetIpToS != null) {
604 OFActionNetworkTypeOfService ofa =
605 new OFActionNetworkTypeOfService(actionSetIpToS.ipToS());
606 openFlowActions.add(ofa);
607 actionsLen += ofa.getLength();
608 }
609
610 if (actionSetTcpUdpSrcPort != null) {
611 OFActionTransportLayerSource ofa =
612 new OFActionTransportLayerSource(actionSetTcpUdpSrcPort.port());
613 openFlowActions.add(ofa);
614 actionsLen += ofa.getLength();
615 }
616
617 if (actionSetTcpUdpDstPort != null) {
618 OFActionTransportLayerDestination ofa =
619 new OFActionTransportLayerDestination(actionSetTcpUdpDstPort.port());
620 openFlowActions.add(ofa);
621 actionsLen += ofa.getLength();
622 }
623
624 if (actionEnqueue != null) {
625 OFActionEnqueue ofa =
626 new OFActionEnqueue(actionEnqueue.port().value(),
627 actionEnqueue.queueId());
628 openFlowActions.add(ofa);
629 actionsLen += ofa.getLength();
630 }
631 }
632
633 fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
634 .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
635 .setPriority(PRIORITY_DEFAULT)
636 .setBufferId(OFPacketOut.BUFFER_ID_NONE)
637 .setCookie(cookie)
638 .setCommand(flowModCommand)
639 .setMatch(match)
640 .setActions(openFlowActions)
641 .setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLen);
642 fm.setOutPort(OFPort.OFPP_NONE.getValue());
643 if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
644 (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
645 if (actionOutputPort != null)
646 fm.setOutPort(actionOutputPort);
647 }
648
649 //
650 // TODO: Set the following flag
651 // fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
652 // See method ForwardingBase::pushRoute()
653 //
654
655 //
656 // Write the message to the switch
657 //
658 try {
659 messageDamper.write(mySwitch, fm, null);
660 mySwitch.flush();
661 //
662 // TODO: We should use the OpenFlow Barrier mechanism
663 // to check for errors, and update the SwitchState
664 // for a flow entry after the Barrier message is
665 // is received.
666 //
667 // TODO: The FlowEntry Object in Titan should be set
668 // to FE_SWITCH_UPDATED.
669 //
670 } catch (IOException e) {
671 log.error("Failure writing flow mod from network map", e);
672 return false;
673 }
674 return true;
675 }
676}