blob: 9741b04dc5862ec3e5d0be0e2e43060567fc232b [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);
Pavlin Radoslavov5db7c412013-10-29 10:50:28 -0700205 else
206 flowEntryActions = new FlowEntryActions();
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700207 for (FlowEntryAction action : flowEntryActions.actions()) {
208 ActionOutput actionOutput = action.actionOutput();
209 ActionSetVlanId actionSetVlanId = action.actionSetVlanId();
210 ActionSetVlanPriority actionSetVlanPriority = action.actionSetVlanPriority();
211 ActionStripVlan actionStripVlan = action.actionStripVlan();
212 ActionSetEthernetAddr actionSetEthernetSrcAddr = action.actionSetEthernetSrcAddr();
213 ActionSetEthernetAddr actionSetEthernetDstAddr = action.actionSetEthernetDstAddr();
214 ActionSetIPv4Addr actionSetIPv4SrcAddr = action.actionSetIPv4SrcAddr();
215 ActionSetIPv4Addr actionSetIPv4DstAddr = action.actionSetIPv4DstAddr();
216 ActionSetIpToS actionSetIpToS = action.actionSetIpToS();
217 ActionSetTcpUdpPort actionSetTcpUdpSrcPort = action.actionSetTcpUdpSrcPort();
218 ActionSetTcpUdpPort actionSetTcpUdpDstPort = action.actionSetTcpUdpDstPort();
219 ActionEnqueue actionEnqueue = action.actionEnqueue();
220
221 if (actionOutput != null) {
222 actionOutputPort = actionOutput.port().value();
223 // XXX: The max length is hard-coded for now
224 OFActionOutput ofa =
225 new OFActionOutput(actionOutput.port().value(),
226 (short)0xffff);
227 openFlowActions.add(ofa);
228 actionsLen += ofa.getLength();
229 }
230
231 if (actionSetVlanId != null) {
232 OFActionVirtualLanIdentifier ofa =
233 new OFActionVirtualLanIdentifier(actionSetVlanId.vlanId());
234 openFlowActions.add(ofa);
235 actionsLen += ofa.getLength();
236 }
237
238 if (actionSetVlanPriority != null) {
239 OFActionVirtualLanPriorityCodePoint ofa =
240 new OFActionVirtualLanPriorityCodePoint(actionSetVlanPriority.vlanPriority());
241 openFlowActions.add(ofa);
242 actionsLen += ofa.getLength();
243 }
244
245 if (actionStripVlan != null) {
246 if (actionStripVlan.stripVlan() == true) {
247 OFActionStripVirtualLan ofa = new OFActionStripVirtualLan();
248 openFlowActions.add(ofa);
249 actionsLen += ofa.getLength();
250 }
251 }
252
253 if (actionSetEthernetSrcAddr != null) {
254 OFActionDataLayerSource ofa =
255 new OFActionDataLayerSource(actionSetEthernetSrcAddr.addr().toBytes());
256 openFlowActions.add(ofa);
257 actionsLen += ofa.getLength();
258 }
259
260 if (actionSetEthernetDstAddr != null) {
261 OFActionDataLayerDestination ofa =
262 new OFActionDataLayerDestination(actionSetEthernetDstAddr.addr().toBytes());
263 openFlowActions.add(ofa);
264 actionsLen += ofa.getLength();
265 }
266
267 if (actionSetIPv4SrcAddr != null) {
268 OFActionNetworkLayerSource ofa =
269 new OFActionNetworkLayerSource(actionSetIPv4SrcAddr.addr().value());
270 openFlowActions.add(ofa);
271 actionsLen += ofa.getLength();
272 }
273
274 if (actionSetIPv4DstAddr != null) {
275 OFActionNetworkLayerDestination ofa =
276 new OFActionNetworkLayerDestination(actionSetIPv4DstAddr.addr().value());
277 openFlowActions.add(ofa);
278 actionsLen += ofa.getLength();
279 }
280
281 if (actionSetIpToS != null) {
282 OFActionNetworkTypeOfService ofa =
283 new OFActionNetworkTypeOfService(actionSetIpToS.ipToS());
284 openFlowActions.add(ofa);
285 actionsLen += ofa.getLength();
286 }
287
288 if (actionSetTcpUdpSrcPort != null) {
289 OFActionTransportLayerSource ofa =
290 new OFActionTransportLayerSource(actionSetTcpUdpSrcPort.port());
291 openFlowActions.add(ofa);
292 actionsLen += ofa.getLength();
293 }
294
295 if (actionSetTcpUdpDstPort != null) {
296 OFActionTransportLayerDestination ofa =
297 new OFActionTransportLayerDestination(actionSetTcpUdpDstPort.port());
298 openFlowActions.add(ofa);
299 actionsLen += ofa.getLength();
300 }
301
302 if (actionEnqueue != null) {
303 OFActionEnqueue ofa =
304 new OFActionEnqueue(actionEnqueue.port().value(),
305 actionEnqueue.queueId());
306 openFlowActions.add(ofa);
307 actionsLen += ofa.getLength();
308 }
309 }
310
311 fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
312 .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
313 .setPriority(PRIORITY_DEFAULT)
314 .setBufferId(OFPacketOut.BUFFER_ID_NONE)
315 .setCookie(cookie)
316 .setCommand(flowModCommand)
317 .setMatch(match)
318 .setActions(openFlowActions)
319 .setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLen);
320 fm.setOutPort(OFPort.OFPP_NONE.getValue());
321 if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
322 (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
323 if (actionOutputPort != null)
324 fm.setOutPort(actionOutputPort);
325 }
326
327 //
328 // TODO: Set the following flag
329 // fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
330 // See method ForwardingBase::pushRoute()
331 //
332
333 //
334 // Write the message to the switch
335 //
336 log.debug("MEASUREMENT: Installing flow entry " + userState +
337 " into switch DPID: " +
338 mySwitch.getStringId() +
339 " flowEntryId: " + flowEntryId.toString() +
340 " srcMac: " + matchSrcMac + " dstMac: " + matchDstMac +
341 " inPort: " + matchInPort + " outPort: " + actionOutputPort
342 );
343 try {
344 messageDamper.write(mySwitch, fm, null);
345 mySwitch.flush();
346 //
347 // TODO: We should use the OpenFlow Barrier mechanism
348 // to check for errors, and update the SwitchState
349 // for a flow entry after the Barrier message is
350 // is received.
351 //
352 flowEntryObj.setSwitchState("FE_SWITCH_UPDATED");
353 } catch (IOException e) {
354 log.error("Failure writing flow mod from network map", e);
355 return false;
356 }
357
358 return true;
359 }
360
361 /**
362 * Install a Flow Entry on a switch.
363 *
364 * @param messageFactory the OpenFlow message factory to use.
365 * @maram messageDamper the OpenFlow message damper to use.
366 * @param mySwitch the switch to install the Flow Entry into.
367 * @param flowPath the flow path for the flow entry to install.
368 * @param flowEntry the flow entry to install.
369 * @return true on success, otherwise false.
370 */
371 static boolean installFlowEntry(BasicFactory messageFactory,
372 OFMessageDamper messageDamper,
373 IOFSwitch mySwitch, FlowPath flowPath,
374 FlowEntry flowEntry) {
375 //
376 // Create the OpenFlow Flow Modification Entry to push
377 //
378 OFFlowMod fm = (OFFlowMod)messageFactory.getMessage(OFType.FLOW_MOD);
379 long cookie = flowEntry.flowEntryId().value();
380
381 short flowModCommand = OFFlowMod.OFPFC_ADD;
382 if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_ADD) {
383 flowModCommand = OFFlowMod.OFPFC_ADD;
384 } else if (flowEntry.flowEntryUserState() == FlowEntryUserState.FE_USER_MODIFY) {
385 flowModCommand = OFFlowMod.OFPFC_MODIFY_STRICT;
386 } else if (flowEntry.flowEntryUserState() == FlowEntryUserState.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 flowEntry.flowEntryId().toString(),
392 flowEntry.flowEntryUserState());
393 return false;
394 }
395
396 //
397 // Fetch the match conditions.
398 //
399 // NOTE: The Flow matching conditions common for all Flow Entries are
400 // used ONLY if a Flow Entry does NOT have the corresponding matching
401 // condition set.
402 //
403 OFMatch match = new OFMatch();
404 match.setWildcards(OFMatch.OFPFW_ALL);
405 FlowEntryMatch flowPathMatch = flowPath.flowEntryMatch();
406 FlowEntryMatch flowEntryMatch = flowEntry.flowEntryMatch();
407
408 // Match the Incoming Port
409 Port matchInPort = flowEntryMatch.inPort();
410 if (matchInPort != null) {
411 match.setInputPort(matchInPort.value());
412 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_IN_PORT);
413 }
414
415 // Match the Source MAC address
416 MACAddress matchSrcMac = flowEntryMatch.srcMac();
417 if ((matchSrcMac == null) && (flowPathMatch != null)) {
418 matchSrcMac = flowPathMatch.srcMac();
419 }
420 if (matchSrcMac != null) {
421 match.setDataLayerSource(matchSrcMac.toString());
422 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
423 }
424
425 // Match the Destination MAC address
426 MACAddress matchDstMac = flowEntryMatch.dstMac();
427 if ((matchDstMac == null) && (flowPathMatch != null)) {
428 matchDstMac = flowPathMatch.dstMac();
429 }
430 if (matchDstMac != null) {
431 match.setDataLayerDestination(matchDstMac.toString());
432 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
433 }
434
435 // Match the Ethernet Frame Type
436 Short matchEthernetFrameType = flowEntryMatch.ethernetFrameType();
437 if ((matchEthernetFrameType == null) && (flowPathMatch != null)) {
438 matchEthernetFrameType = flowPathMatch.ethernetFrameType();
439 }
440 if (matchEthernetFrameType != null) {
441 match.setDataLayerType(matchEthernetFrameType);
442 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
443 }
444
445 // Match the VLAN ID
446 Short matchVlanId = flowEntryMatch.vlanId();
447 if ((matchVlanId == null) && (flowPathMatch != null)) {
448 matchVlanId = flowPathMatch.vlanId();
449 }
450 if (matchVlanId != null) {
451 match.setDataLayerVirtualLan(matchVlanId);
452 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN);
453 }
454
455 // Match the VLAN priority
456 Byte matchVlanPriority = flowEntryMatch.vlanPriority();
457 if ((matchVlanPriority == null) && (flowPathMatch != null)) {
458 matchVlanPriority = flowPathMatch.vlanPriority();
459 }
460 if (matchVlanPriority != null) {
461 match.setDataLayerVirtualLanPriorityCodePoint(matchVlanPriority);
462 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN_PCP);
463 }
464
465 // Match the Source IPv4 Network prefix
466 IPv4Net matchSrcIPv4Net = flowEntryMatch.srcIPv4Net();
467 if ((matchSrcIPv4Net == null) && (flowPathMatch != null)) {
468 matchSrcIPv4Net = flowPathMatch.srcIPv4Net();
469 }
470 if (matchSrcIPv4Net != null) {
471 match.setFromCIDR(matchSrcIPv4Net.toString(), OFMatch.STR_NW_SRC);
472 }
473
474 // Natch the Destination IPv4 Network prefix
475 IPv4Net matchDstIPv4Net = flowEntryMatch.dstIPv4Net();
476 if ((matchDstIPv4Net == null) && (flowPathMatch != null)) {
477 matchDstIPv4Net = flowPathMatch.dstIPv4Net();
478 }
479 if (matchDstIPv4Net != null) {
480 match.setFromCIDR(matchDstIPv4Net.toString(), OFMatch.STR_NW_DST);
481 }
482
483 // Match the IP protocol
484 Byte matchIpProto = flowEntryMatch.ipProto();
485 if ((matchIpProto == null) && (flowPathMatch != null)) {
486 matchIpProto = flowPathMatch.ipProto();
487 }
488 if (matchIpProto != null) {
489 match.setNetworkProtocol(matchIpProto);
490 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_PROTO);
491 }
492
493 // Match the IP ToS (DSCP field, 6 bits)
494 Byte matchIpToS = flowEntryMatch.ipToS();
495 if ((matchIpToS == null) && (flowPathMatch != null)) {
496 matchIpToS = flowPathMatch.ipToS();
497 }
498 if (matchIpToS != null) {
499 match.setNetworkTypeOfService(matchIpToS);
500 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_TOS);
501 }
502
503 // Match the Source TCP/UDP port
504 Short matchSrcTcpUdpPort = flowEntryMatch.srcTcpUdpPort();
505 if ((matchSrcTcpUdpPort == null) && (flowPathMatch != null)) {
506 matchSrcTcpUdpPort = flowPathMatch.srcTcpUdpPort();
507 }
508 if (matchSrcTcpUdpPort != null) {
509 match.setTransportSource(matchSrcTcpUdpPort);
510 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
511 }
512
513 // Match the Destination TCP/UDP port
514 Short matchDstTcpUdpPort = flowEntryMatch.dstTcpUdpPort();
515 if ((matchDstTcpUdpPort == null) && (flowPathMatch != null)) {
516 matchDstTcpUdpPort = flowPathMatch.dstTcpUdpPort();
517 }
518 if (matchDstTcpUdpPort != null) {
519 match.setTransportDestination(matchDstTcpUdpPort);
520 match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_DST);
521 }
522
523 //
524 // Fetch the actions
525 //
526 Short actionOutputPort = null;
527 List<OFAction> openFlowActions = new ArrayList<OFAction>();
528 int actionsLen = 0;
529 FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
530 //
531 for (FlowEntryAction action : flowEntryActions.actions()) {
532 ActionOutput actionOutput = action.actionOutput();
533 ActionSetVlanId actionSetVlanId = action.actionSetVlanId();
534 ActionSetVlanPriority actionSetVlanPriority = action.actionSetVlanPriority();
535 ActionStripVlan actionStripVlan = action.actionStripVlan();
536 ActionSetEthernetAddr actionSetEthernetSrcAddr = action.actionSetEthernetSrcAddr();
537 ActionSetEthernetAddr actionSetEthernetDstAddr = action.actionSetEthernetDstAddr();
538 ActionSetIPv4Addr actionSetIPv4SrcAddr = action.actionSetIPv4SrcAddr();
539 ActionSetIPv4Addr actionSetIPv4DstAddr = action.actionSetIPv4DstAddr();
540 ActionSetIpToS actionSetIpToS = action.actionSetIpToS();
541 ActionSetTcpUdpPort actionSetTcpUdpSrcPort = action.actionSetTcpUdpSrcPort();
542 ActionSetTcpUdpPort actionSetTcpUdpDstPort = action.actionSetTcpUdpDstPort();
543 ActionEnqueue actionEnqueue = action.actionEnqueue();
544
545 if (actionOutput != null) {
546 actionOutputPort = actionOutput.port().value();
547 // XXX: The max length is hard-coded for now
548 OFActionOutput ofa =
549 new OFActionOutput(actionOutput.port().value(),
550 (short)0xffff);
551 openFlowActions.add(ofa);
552 actionsLen += ofa.getLength();
553 }
554
555 if (actionSetVlanId != null) {
556 OFActionVirtualLanIdentifier ofa =
557 new OFActionVirtualLanIdentifier(actionSetVlanId.vlanId());
558 openFlowActions.add(ofa);
559 actionsLen += ofa.getLength();
560 }
561
562 if (actionSetVlanPriority != null) {
563 OFActionVirtualLanPriorityCodePoint ofa =
564 new OFActionVirtualLanPriorityCodePoint(actionSetVlanPriority.vlanPriority());
565 openFlowActions.add(ofa);
566 actionsLen += ofa.getLength();
567 }
568
569 if (actionStripVlan != null) {
570 if (actionStripVlan.stripVlan() == true) {
571 OFActionStripVirtualLan ofa = new OFActionStripVirtualLan();
572 openFlowActions.add(ofa);
573 actionsLen += ofa.getLength();
574 }
575 }
576
577 if (actionSetEthernetSrcAddr != null) {
578 OFActionDataLayerSource ofa =
579 new OFActionDataLayerSource(actionSetEthernetSrcAddr.addr().toBytes());
580 openFlowActions.add(ofa);
581 actionsLen += ofa.getLength();
582 }
583
584 if (actionSetEthernetDstAddr != null) {
585 OFActionDataLayerDestination ofa =
586 new OFActionDataLayerDestination(actionSetEthernetDstAddr.addr().toBytes());
587 openFlowActions.add(ofa);
588 actionsLen += ofa.getLength();
589 }
590
591 if (actionSetIPv4SrcAddr != null) {
592 OFActionNetworkLayerSource ofa =
593 new OFActionNetworkLayerSource(actionSetIPv4SrcAddr.addr().value());
594 openFlowActions.add(ofa);
595 actionsLen += ofa.getLength();
596 }
597
598 if (actionSetIPv4DstAddr != null) {
599 OFActionNetworkLayerDestination ofa =
600 new OFActionNetworkLayerDestination(actionSetIPv4DstAddr.addr().value());
601 openFlowActions.add(ofa);
602 actionsLen += ofa.getLength();
603 }
604
605 if (actionSetIpToS != null) {
606 OFActionNetworkTypeOfService ofa =
607 new OFActionNetworkTypeOfService(actionSetIpToS.ipToS());
608 openFlowActions.add(ofa);
609 actionsLen += ofa.getLength();
610 }
611
612 if (actionSetTcpUdpSrcPort != null) {
613 OFActionTransportLayerSource ofa =
614 new OFActionTransportLayerSource(actionSetTcpUdpSrcPort.port());
615 openFlowActions.add(ofa);
616 actionsLen += ofa.getLength();
617 }
618
619 if (actionSetTcpUdpDstPort != null) {
620 OFActionTransportLayerDestination ofa =
621 new OFActionTransportLayerDestination(actionSetTcpUdpDstPort.port());
622 openFlowActions.add(ofa);
623 actionsLen += ofa.getLength();
624 }
625
626 if (actionEnqueue != null) {
627 OFActionEnqueue ofa =
628 new OFActionEnqueue(actionEnqueue.port().value(),
629 actionEnqueue.queueId());
630 openFlowActions.add(ofa);
631 actionsLen += ofa.getLength();
632 }
633 }
634
635 fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
636 .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
637 .setPriority(PRIORITY_DEFAULT)
638 .setBufferId(OFPacketOut.BUFFER_ID_NONE)
639 .setCookie(cookie)
640 .setCommand(flowModCommand)
641 .setMatch(match)
642 .setActions(openFlowActions)
643 .setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLen);
644 fm.setOutPort(OFPort.OFPP_NONE.getValue());
645 if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
646 (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
647 if (actionOutputPort != null)
648 fm.setOutPort(actionOutputPort);
649 }
650
651 //
652 // TODO: Set the following flag
653 // fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
654 // See method ForwardingBase::pushRoute()
655 //
656
657 //
658 // Write the message to the switch
659 //
Pavlin Radoslavov5db7c412013-10-29 10:50:28 -0700660 log.debug("MEASUREMENT: Installing flow entry " +
661 flowEntry.flowEntryUserState() +
662 " into switch DPID: " +
663 mySwitch.getStringId() +
664 " flowEntryId: " + flowEntry.flowEntryId().toString() +
665 " srcMac: " + matchSrcMac + " dstMac: " + matchDstMac +
666 " inPort: " + matchInPort + " outPort: " + actionOutputPort
667 );
Pavlin Radoslavov661c86f2013-10-21 12:40:40 -0700668 try {
669 messageDamper.write(mySwitch, fm, null);
670 mySwitch.flush();
671 //
672 // TODO: We should use the OpenFlow Barrier mechanism
673 // to check for errors, and update the SwitchState
674 // for a flow entry after the Barrier message is
675 // is received.
676 //
677 // TODO: The FlowEntry Object in Titan should be set
678 // to FE_SWITCH_UPDATED.
679 //
680 } catch (IOException e) {
681 log.error("Failure writing flow mod from network map", e);
682 return false;
683 }
684 return true;
685 }
686}