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