2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.protocol_plugin.openflow.internal;
11 import java.math.BigInteger;
12 import java.net.InetAddress;
13 import java.net.UnknownHostException;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.List;
19 import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6FlowMod;
20 import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Match;
21 import org.opendaylight.controller.sal.action.Action;
22 import org.opendaylight.controller.sal.action.ActionType;
23 import org.opendaylight.controller.sal.action.Controller;
24 import org.opendaylight.controller.sal.action.Drop;
25 import org.opendaylight.controller.sal.action.Enqueue;
26 import org.opendaylight.controller.sal.action.Flood;
27 import org.opendaylight.controller.sal.action.FloodAll;
28 import org.opendaylight.controller.sal.action.HwPath;
29 import org.opendaylight.controller.sal.action.Loopback;
30 import org.opendaylight.controller.sal.action.Output;
31 import org.opendaylight.controller.sal.action.PopVlan;
32 import org.opendaylight.controller.sal.action.SetDlDst;
33 import org.opendaylight.controller.sal.action.SetDlSrc;
34 import org.opendaylight.controller.sal.action.SetNwDst;
35 import org.opendaylight.controller.sal.action.SetNwSrc;
36 import org.opendaylight.controller.sal.action.SetNwTos;
37 import org.opendaylight.controller.sal.action.SetTpDst;
38 import org.opendaylight.controller.sal.action.SetTpSrc;
39 import org.opendaylight.controller.sal.action.SetVlanId;
40 import org.opendaylight.controller.sal.action.SetVlanPcp;
41 import org.opendaylight.controller.sal.action.SwPath;
42 import org.opendaylight.controller.sal.core.Node;
43 import org.opendaylight.controller.sal.core.NodeConnector;
44 import org.opendaylight.controller.sal.flowprogrammer.Flow;
45 import org.opendaylight.controller.sal.match.Match;
46 import org.opendaylight.controller.sal.match.MatchField;
47 import org.opendaylight.controller.sal.match.MatchType;
48 import org.opendaylight.controller.sal.utils.NetUtils;
49 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
50 import org.openflow.protocol.OFFlowMod;
51 import org.openflow.protocol.OFMatch;
52 import org.openflow.protocol.OFMessage;
53 import org.openflow.protocol.OFPacketOut;
54 import org.openflow.protocol.OFPort;
55 import org.openflow.protocol.OFVendor;
56 import org.openflow.protocol.action.OFAction;
57 import org.openflow.protocol.action.OFActionDataLayer;
58 import org.openflow.protocol.action.OFActionDataLayerDestination;
59 import org.openflow.protocol.action.OFActionDataLayerSource;
60 import org.openflow.protocol.action.OFActionEnqueue;
61 import org.openflow.protocol.action.OFActionNetworkLayerAddress;
62 import org.openflow.protocol.action.OFActionNetworkLayerDestination;
63 import org.openflow.protocol.action.OFActionNetworkLayerSource;
64 import org.openflow.protocol.action.OFActionNetworkTypeOfService;
65 import org.openflow.protocol.action.OFActionOutput;
66 import org.openflow.protocol.action.OFActionStripVirtualLan;
67 import org.openflow.protocol.action.OFActionTransportLayer;
68 import org.openflow.protocol.action.OFActionTransportLayerDestination;
69 import org.openflow.protocol.action.OFActionTransportLayerSource;
70 import org.openflow.protocol.action.OFActionVirtualLanIdentifier;
71 import org.openflow.protocol.action.OFActionVirtualLanPriorityCodePoint;
72 import org.openflow.util.U16;
73 import org.openflow.util.U32;
74 import org.slf4j.Logger;
75 import org.slf4j.LoggerFactory;
78 * Utility class for converting a SAL Flow into the OF flow and vice-versa
80 public class FlowConverter {
81 protected static final Logger logger = LoggerFactory
82 .getLogger(FlowConverter.class);
85 * The value 0xffff (OFP_VLAN_NONE) is used to indicate
86 * that no VLAN ID is set for OF Flow.
88 private static final short OFP_VLAN_NONE = (short) 0xffff;
90 private Flow flow; // SAL Flow
91 private OFMatch ofMatch; // OF 1.0 match or OF 1.0 + IPv6 extension match
92 private List<OFAction> actionsList; // OF 1.0 actions
93 private int actionsLength;
94 private boolean isIPv6;
96 public FlowConverter(OFMatch ofMatch, List<OFAction> actionsList) {
97 this.ofMatch = ofMatch;
98 this.actionsList = actionsList;
99 this.actionsLength = 0;
101 this.isIPv6 = ofMatch instanceof V6Match;
104 public FlowConverter(Flow flow) {
106 this.actionsList = null;
107 this.actionsLength = 0;
109 this.isIPv6 = flow.isIPv6();
113 * Returns the match in OF 1.0 (OFMatch) form or OF 1.0 + IPv6 extensions
118 public OFMatch getOFMatch() {
119 if (ofMatch == null) {
120 Match match = flow.getMatch();
121 ofMatch = (isIPv6) ? new V6Match() : new OFMatch();
123 int wildcards = OFMatch.OFPFW_ALL;
124 if (match.isPresent(MatchType.IN_PORT)) {
125 short port = (Short) ((NodeConnector) match.getField(
126 MatchType.IN_PORT).getValue()).getID();
128 ofMatch.setInputPort(port);
129 wildcards &= ~OFMatch.OFPFW_IN_PORT;
131 ((V6Match) ofMatch).setInputPort(port, (short) 0);
134 if (match.isPresent(MatchType.DL_SRC)) {
135 byte[] srcMac = (byte[]) match.getField(MatchType.DL_SRC)
138 ofMatch.setDataLayerSource(srcMac.clone());
139 wildcards &= ~OFMatch.OFPFW_DL_SRC;
141 ((V6Match) ofMatch).setDataLayerSource(srcMac, null);
144 if (match.isPresent(MatchType.DL_DST)) {
145 byte[] dstMac = (byte[]) match.getField(MatchType.DL_DST)
148 ofMatch.setDataLayerDestination(dstMac.clone());
149 wildcards &= ~OFMatch.OFPFW_DL_DST;
151 ((V6Match) ofMatch).setDataLayerDestination(dstMac, null);
154 if (match.isPresent(MatchType.DL_VLAN)) {
155 short vlan = (Short) match.getField(MatchType.DL_VLAN)
157 if (vlan == MatchType.DL_VLAN_NONE) {
158 vlan = OFP_VLAN_NONE;
161 ofMatch.setDataLayerVirtualLan(vlan);
162 wildcards &= ~OFMatch.OFPFW_DL_VLAN;
164 ((V6Match) ofMatch).setDataLayerVirtualLan(vlan, (short) 0);
167 if (match.isPresent(MatchType.DL_VLAN_PR)) {
168 byte vlanPr = (Byte) match.getField(MatchType.DL_VLAN_PR)
171 ofMatch.setDataLayerVirtualLanPriorityCodePoint(vlanPr);
172 wildcards &= ~OFMatch.OFPFW_DL_VLAN_PCP;
175 .setDataLayerVirtualLanPriorityCodePoint(vlanPr,
179 if (match.isPresent(MatchType.DL_TYPE)) {
180 short ethType = (Short) match.getField(MatchType.DL_TYPE)
183 ofMatch.setDataLayerType(ethType);
184 wildcards &= ~OFMatch.OFPFW_DL_TYPE;
186 ((V6Match) ofMatch).setDataLayerType(ethType, (short) 0);
189 if (match.isPresent(MatchType.NW_TOS)) {
191 * OF 1.0 switch expects the TOS as the 6 msb in the byte. it is
192 * actually the DSCP field followed by a zero ECN
194 byte tos = (Byte) match.getField(MatchType.NW_TOS).getValue();
195 byte dscp = (byte) (tos << 2);
197 ofMatch.setNetworkTypeOfService(dscp);
198 wildcards &= ~OFMatch.OFPFW_NW_TOS;
200 ((V6Match) ofMatch).setNetworkTypeOfService(dscp, (byte) 0);
203 if (match.isPresent(MatchType.NW_PROTO)) {
204 byte proto = (Byte) match.getField(MatchType.NW_PROTO)
207 ofMatch.setNetworkProtocol(proto);
208 wildcards &= ~OFMatch.OFPFW_NW_PROTO;
210 ((V6Match) ofMatch).setNetworkProtocol(proto, (byte) 0);
213 if (match.isPresent(MatchType.NW_SRC)) {
214 InetAddress address = (InetAddress) match.getField(MatchType.NW_SRC).getValue();
215 InetAddress mask = (InetAddress) match.getField(MatchType.NW_SRC).getMask();
217 ofMatch.setNetworkSource(NetUtils.byteArray4ToInt(address.getAddress()));
218 int maskLength = (mask == null) ? 32 : NetUtils.getSubnetMaskLength(mask);
219 wildcards = (wildcards & ~OFMatch.OFPFW_NW_SRC_MASK) | ((32 - maskLength) << OFMatch.OFPFW_NW_SRC_SHIFT);
221 ((V6Match) ofMatch).setNetworkSource(address, mask);
224 if (match.isPresent(MatchType.NW_DST)) {
225 InetAddress address = (InetAddress) match.getField(MatchType.NW_DST).getValue();
226 InetAddress mask = (InetAddress) match.getField(MatchType.NW_DST).getMask();
228 ofMatch.setNetworkDestination(NetUtils.byteArray4ToInt(address.getAddress()));
229 int maskLength = (mask == null) ? 32 : NetUtils.getSubnetMaskLength(mask);
230 wildcards = (wildcards & ~OFMatch.OFPFW_NW_DST_MASK) | ((32 - maskLength) << OFMatch.OFPFW_NW_DST_SHIFT);
232 ((V6Match) ofMatch).setNetworkDestination(address, mask);
235 if (match.isPresent(MatchType.TP_SRC)) {
236 short port = (Short) match.getField(MatchType.TP_SRC)
239 ofMatch.setTransportSource(port);
240 wildcards &= ~OFMatch.OFPFW_TP_SRC;
242 ((V6Match) ofMatch).setTransportSource(port, (short) 0);
245 if (match.isPresent(MatchType.TP_DST)) {
246 short port = (Short) match.getField(MatchType.TP_DST)
249 ofMatch.setTransportDestination(port);
250 wildcards &= ~OFMatch.OFPFW_TP_DST;
253 .setTransportDestination(port, (short) 0);
258 ofMatch.setWildcards(U32.t(Long.valueOf(wildcards)));
261 logger.trace("SAL Match: {} Openflow Match: {}", flow.getMatch(),
267 * Returns the list of actions in OF 1.0 form
271 public List<OFAction> getOFActions() {
272 if (this.actionsList == null) {
273 actionsList = new ArrayList<OFAction>();
274 for (Action action : flow.getActions()) {
275 if (action.getType() == ActionType.OUTPUT) {
276 Output a = (Output) action;
277 OFActionOutput ofAction = new OFActionOutput();
278 ofAction.setMaxLength((short) 0xffff);
279 ofAction.setPort(PortConverter.toOFPort(a.getPort()));
280 actionsList.add(ofAction);
281 actionsLength += OFActionOutput.MINIMUM_LENGTH;
284 if (action.getType() == ActionType.ENQUEUE) {
285 Enqueue a = (Enqueue) action;
286 OFActionEnqueue ofAction = new OFActionEnqueue();
287 ofAction.setPort(PortConverter.toOFPort(a.getPort()));
288 ofAction.setQueueId(a.getQueue());
289 actionsList.add(ofAction);
290 actionsLength += OFActionEnqueue.MINIMUM_LENGTH;
293 if (action.getType() == ActionType.DROP) {
296 if (action.getType() == ActionType.LOOPBACK) {
297 OFActionOutput ofAction = new OFActionOutput();
298 ofAction.setPort(OFPort.OFPP_IN_PORT.getValue());
299 actionsList.add(ofAction);
300 actionsLength += OFActionOutput.MINIMUM_LENGTH;
303 if (action.getType() == ActionType.FLOOD) {
304 OFActionOutput ofAction = new OFActionOutput();
305 ofAction.setPort(OFPort.OFPP_FLOOD.getValue());
306 actionsList.add(ofAction);
307 actionsLength += OFActionOutput.MINIMUM_LENGTH;
310 if (action.getType() == ActionType.FLOOD_ALL) {
311 OFActionOutput ofAction = new OFActionOutput();
312 ofAction.setPort(OFPort.OFPP_ALL.getValue());
313 actionsList.add(ofAction);
314 actionsLength += OFActionOutput.MINIMUM_LENGTH;
317 if (action.getType() == ActionType.CONTROLLER) {
318 OFActionOutput ofAction = new OFActionOutput();
319 ofAction.setPort(OFPort.OFPP_CONTROLLER.getValue());
320 // We want the whole frame hitting the match be sent to the
322 ofAction.setMaxLength((short) 0xffff);
323 actionsList.add(ofAction);
324 actionsLength += OFActionOutput.MINIMUM_LENGTH;
327 if (action.getType() == ActionType.SW_PATH) {
328 OFActionOutput ofAction = new OFActionOutput();
329 ofAction.setPort(OFPort.OFPP_LOCAL.getValue());
330 actionsList.add(ofAction);
331 actionsLength += OFActionOutput.MINIMUM_LENGTH;
334 if (action.getType() == ActionType.HW_PATH) {
335 OFActionOutput ofAction = new OFActionOutput();
336 ofAction.setPort(OFPort.OFPP_NORMAL.getValue());
337 actionsList.add(ofAction);
338 actionsLength += OFActionOutput.MINIMUM_LENGTH;
341 if (action.getType() == ActionType.SET_VLAN_ID) {
342 SetVlanId a = (SetVlanId) action;
343 OFActionVirtualLanIdentifier ofAction = new OFActionVirtualLanIdentifier();
344 ofAction.setVirtualLanIdentifier((short) a.getVlanId());
345 actionsList.add(ofAction);
346 actionsLength += OFActionVirtualLanIdentifier.MINIMUM_LENGTH;
349 if (action.getType() == ActionType.SET_VLAN_PCP) {
350 SetVlanPcp a = (SetVlanPcp) action;
351 OFActionVirtualLanPriorityCodePoint ofAction = new OFActionVirtualLanPriorityCodePoint();
352 ofAction.setVirtualLanPriorityCodePoint(Integer.valueOf(
353 a.getPcp()).byteValue());
354 actionsList.add(ofAction);
355 actionsLength += OFActionVirtualLanPriorityCodePoint.MINIMUM_LENGTH;
358 if (action.getType() == ActionType.POP_VLAN) {
359 OFActionStripVirtualLan ofAction = new OFActionStripVirtualLan();
360 actionsList.add(ofAction);
361 actionsLength += OFActionStripVirtualLan.MINIMUM_LENGTH;
364 if (action.getType() == ActionType.SET_DL_SRC) {
365 SetDlSrc a = (SetDlSrc) action;
366 OFActionDataLayerSource ofAction = new OFActionDataLayerSource();
367 ofAction.setDataLayerAddress(a.getDlAddress());
368 actionsList.add(ofAction);
369 actionsLength += OFActionDataLayer.MINIMUM_LENGTH;
372 if (action.getType() == ActionType.SET_DL_DST) {
373 SetDlDst a = (SetDlDst) action;
374 OFActionDataLayerDestination ofAction = new OFActionDataLayerDestination();
375 ofAction.setDataLayerAddress(a.getDlAddress());
376 actionsList.add(ofAction);
377 actionsLength += OFActionDataLayer.MINIMUM_LENGTH;
380 if (action.getType() == ActionType.SET_NW_SRC) {
381 SetNwSrc a = (SetNwSrc) action;
382 OFActionNetworkLayerSource ofAction = new OFActionNetworkLayerSource();
383 ofAction.setNetworkAddress(NetUtils.byteArray4ToInt(a
384 .getAddress().getAddress()));
385 actionsList.add(ofAction);
386 actionsLength += OFActionNetworkLayerAddress.MINIMUM_LENGTH;
389 if (action.getType() == ActionType.SET_NW_DST) {
390 SetNwDst a = (SetNwDst) action;
391 OFActionNetworkLayerDestination ofAction = new OFActionNetworkLayerDestination();
392 ofAction.setNetworkAddress(NetUtils.byteArray4ToInt(a
393 .getAddress().getAddress()));
394 actionsList.add(ofAction);
395 actionsLength += OFActionNetworkLayerAddress.MINIMUM_LENGTH;
398 if (action.getType() == ActionType.SET_NW_TOS) {
399 SetNwTos a = (SetNwTos) action;
400 OFActionNetworkTypeOfService ofAction = new OFActionNetworkTypeOfService();
401 ofAction.setNetworkTypeOfService(Integer.valueOf(
402 a.getNwTos()).byteValue());
403 actionsList.add(ofAction);
404 actionsLength += OFActionNetworkTypeOfService.MINIMUM_LENGTH;
407 if (action.getType() == ActionType.SET_TP_SRC) {
408 SetTpSrc a = (SetTpSrc) action;
409 OFActionTransportLayerSource ofAction = new OFActionTransportLayerSource();
410 ofAction.setTransportPort(Integer.valueOf(a.getPort())
412 actionsList.add(ofAction);
413 actionsLength += OFActionTransportLayer.MINIMUM_LENGTH;
416 if (action.getType() == ActionType.SET_TP_DST) {
417 SetTpDst a = (SetTpDst) action;
418 OFActionTransportLayerDestination ofAction = new OFActionTransportLayerDestination();
419 ofAction.setTransportPort(Integer.valueOf(a.getPort())
421 actionsList.add(ofAction);
422 actionsLength += OFActionTransportLayer.MINIMUM_LENGTH;
425 if (action.getType() == ActionType.SET_NEXT_HOP) {
426 logger.warn("Unsupported action: {}", action);
431 logger.trace("SAL Actions: {} Openflow Actions: {}", flow.getActions(),
437 * Utility to convert a SAL flow to an OF 1.0 (OFFlowMod) or to an OF 1.0 +
438 * IPv6 extension (V6FlowMod) Flow modifier Message
445 public OFMessage getOFFlowMod(short command, OFPort port) {
446 OFMessage fm = (isIPv6) ? new V6FlowMod() : new OFFlowMod();
447 if (this.ofMatch == null) {
450 if (this.actionsList == null) {
454 ((OFFlowMod) fm).setMatch(this.ofMatch);
455 ((OFFlowMod) fm).setActions(this.actionsList);
456 ((OFFlowMod) fm).setPriority(flow.getPriority());
457 ((OFFlowMod) fm).setCookie(flow.getId());
458 ((OFFlowMod) fm).setBufferId(OFPacketOut.BUFFER_ID_NONE);
459 ((OFFlowMod) fm).setLength(U16.t(OFFlowMod.MINIMUM_LENGTH
461 ((OFFlowMod) fm).setIdleTimeout(flow.getIdleTimeout());
462 ((OFFlowMod) fm).setHardTimeout(flow.getHardTimeout());
463 ((OFFlowMod) fm).setCommand(command);
465 ((OFFlowMod) fm).setOutPort(port);
467 if (command == OFFlowMod.OFPFC_ADD || command == OFFlowMod.OFPFC_MODIFY
468 || command == OFFlowMod.OFPFC_MODIFY_STRICT) {
469 // Instruct switch to let controller know when flow is removed
470 ((OFFlowMod) fm).setFlags((short) 1);
473 ((V6FlowMod) fm).setVendor();
474 ((V6FlowMod) fm).setMatch((V6Match) ofMatch);
475 ((V6FlowMod) fm).setActions(this.actionsList);
476 ((V6FlowMod) fm).setPriority(flow.getPriority());
477 ((V6FlowMod) fm).setCookie(flow.getId());
478 ((V6FlowMod) fm).setLength(U16.t(OFVendor.MINIMUM_LENGTH
479 + ((V6Match) ofMatch).getIPv6ExtMinHdrLen()
480 + ((V6Match) ofMatch).getIPv6MatchLen()
481 + ((V6Match) ofMatch).getPadSize() + actionsLength));
482 ((V6FlowMod) fm).setIdleTimeout(flow.getIdleTimeout());
483 ((V6FlowMod) fm).setHardTimeout(flow.getHardTimeout());
484 ((V6FlowMod) fm).setCommand(command);
486 ((V6FlowMod) fm).setOutPort(port);
488 if (command == OFFlowMod.OFPFC_ADD || command == OFFlowMod.OFPFC_MODIFY
489 || command == OFFlowMod.OFPFC_MODIFY_STRICT) {
490 // Instruct switch to let controller know when flow is removed
491 ((V6FlowMod) fm).setFlags((short) 1);
494 logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch,
496 logger.trace("Openflow Mod Message: {}", fm);
500 public Flow getFlow(Node node) {
501 if (this.flow == null) {
502 Match salMatch = new Match();
505 * Installed flow may not have a Match defined like in case of a
508 if (ofMatch != null) {
510 // Compute OF1.0 Match
511 if (ofMatch.getInputPort() != 0 && ofMatch.getInputPort() != OFPort.OFPP_LOCAL.getValue()) {
512 salMatch.setField(new MatchField(MatchType.IN_PORT,
513 NodeConnectorCreator.createNodeConnector(
514 ofMatch.getInputPort(), node)));
516 if (ofMatch.getDataLayerSource() != null
518 .isZeroMAC(ofMatch.getDataLayerSource())) {
519 byte srcMac[] = ofMatch.getDataLayerSource();
520 salMatch.setField(new MatchField(MatchType.DL_SRC,
523 if (ofMatch.getDataLayerDestination() != null
524 && !NetUtils.isZeroMAC(ofMatch
525 .getDataLayerDestination())) {
526 byte dstMac[] = ofMatch.getDataLayerDestination();
527 salMatch.setField(new MatchField(MatchType.DL_DST,
530 if (ofMatch.getDataLayerType() != 0) {
531 salMatch.setField(new MatchField(MatchType.DL_TYPE,
532 ofMatch.getDataLayerType()));
534 short vlan = ofMatch.getDataLayerVirtualLan();
536 if (vlan == OFP_VLAN_NONE) {
537 vlan = MatchType.DL_VLAN_NONE;
539 salMatch.setField(new MatchField(MatchType.DL_VLAN,
542 if ((ofMatch.getWildcards() & OFMatch.OFPFW_DL_VLAN_PCP) == 0) {
543 salMatch.setField(MatchType.DL_VLAN_PR, ofMatch
544 .getDataLayerVirtualLanPriorityCodePoint());
546 if (ofMatch.getNetworkSource() != 0) {
547 salMatch.setField(MatchType.NW_SRC, NetUtils
548 .getInetAddress(ofMatch.getNetworkSource()),
549 NetUtils.getInetNetworkMask(
550 ofMatch.getNetworkSourceMaskLen(),
553 if (ofMatch.getNetworkDestination() != 0) {
554 salMatch.setField(MatchType.NW_DST,
555 NetUtils.getInetAddress(ofMatch
556 .getNetworkDestination()),
557 NetUtils.getInetNetworkMask(
558 ofMatch.getNetworkDestinationMaskLen(),
561 if (ofMatch.getNetworkTypeOfService() != 0) {
562 int dscp = NetUtils.getUnsignedByte(ofMatch
563 .getNetworkTypeOfService());
564 byte tos = (byte) (dscp >> 2);
565 salMatch.setField(MatchType.NW_TOS, tos);
567 //TODO: NW protocol 0 is a valid protocol
568 if (ofMatch.getNetworkProtocol() != 0) {
569 salMatch.setField(MatchType.NW_PROTO,
570 ofMatch.getNetworkProtocol());
572 if (ofMatch.getTransportSource() != 0) {
573 salMatch.setField(MatchType.TP_SRC,
574 ofMatch.getTransportSource());
576 if (ofMatch.getTransportDestination() != 0) {
577 salMatch.setField(MatchType.TP_DST,
578 ofMatch.getTransportDestination());
581 // Compute OF1.0 + IPv6 extensions Match
582 V6Match v6Match = (V6Match) ofMatch;
583 if (v6Match.getInputPort() != 0 && v6Match.getInputPort() != OFPort.OFPP_LOCAL.getValue()) {
584 // Mask on input port is not defined
585 salMatch.setField(new MatchField(MatchType.IN_PORT,
586 NodeConnectorCreator.createOFNodeConnector(
587 v6Match.getInputPort(), node)));
589 if (v6Match.getDataLayerSource() != null
591 .isZeroMAC(ofMatch.getDataLayerSource())) {
592 byte srcMac[] = v6Match.getDataLayerSource();
593 salMatch.setField(new MatchField(MatchType.DL_SRC,
596 if (v6Match.getDataLayerDestination() != null
597 && !NetUtils.isZeroMAC(ofMatch
598 .getDataLayerDestination())) {
599 byte dstMac[] = v6Match.getDataLayerDestination();
600 salMatch.setField(new MatchField(MatchType.DL_DST,
603 if (v6Match.getDataLayerType() != 0) {
604 salMatch.setField(new MatchField(MatchType.DL_TYPE,
605 v6Match.getDataLayerType()));
607 short vlan = v6Match.getDataLayerVirtualLan();
609 if (vlan == OFP_VLAN_NONE) {
610 vlan = MatchType.DL_VLAN_NONE;
612 salMatch.setField(new MatchField(MatchType.DL_VLAN,
615 if ((v6Match.getWildcards() & OFMatch.OFPFW_DL_VLAN_PCP) == 0) {
616 salMatch.setField(MatchType.DL_VLAN_PR, v6Match
617 .getDataLayerVirtualLanPriorityCodePoint());
619 // V6Match may carry IPv4 address
620 if (v6Match.getNetworkSrc() != null) {
621 salMatch.setField(MatchType.NW_SRC,
622 v6Match.getNetworkSrc(),
623 v6Match.getNetworkSourceMask());
624 } else if (v6Match.getNetworkSource() != 0) {
625 salMatch.setField(MatchType.NW_SRC, NetUtils
626 .getInetAddress(v6Match.getNetworkSource()),
627 NetUtils.getInetNetworkMask(
628 v6Match.getNetworkSourceMaskLen(),
631 // V6Match may carry IPv4 address
632 if (v6Match.getNetworkDest() != null) {
633 salMatch.setField(MatchType.NW_DST,
634 v6Match.getNetworkDest(),
635 v6Match.getNetworkDestinationMask());
636 } else if (v6Match.getNetworkDestination() != 0) {
637 salMatch.setField(MatchType.NW_DST,
638 NetUtils.getInetAddress(v6Match
639 .getNetworkDestination()),
640 NetUtils.getInetNetworkMask(
641 v6Match.getNetworkDestinationMaskLen(),
644 if (v6Match.getNetworkTypeOfService() != 0) {
645 int dscp = NetUtils.getUnsignedByte(v6Match
646 .getNetworkTypeOfService());
647 byte tos = (byte) (dscp >> 2);
648 salMatch.setField(MatchType.NW_TOS, tos);
650 if (v6Match.getNetworkProtocol() != 0) {
651 salMatch.setField(MatchType.NW_PROTO,
652 v6Match.getNetworkProtocol());
654 if (v6Match.getTransportSource() != 0) {
655 salMatch.setField(MatchType.TP_SRC,
656 (v6Match.getTransportSource()));
658 if (v6Match.getTransportDestination() != 0) {
659 salMatch.setField(MatchType.TP_DST,
660 (v6Match.getTransportDestination()));
666 Action salAction = null;
667 List<Action> salActionList = new ArrayList<Action>();
668 if (actionsList == null) {
669 salActionList.add(new Drop());
671 for (OFAction ofAction : actionsList) {
672 if (ofAction instanceof OFActionOutput) {
673 short ofPort = ((OFActionOutput) ofAction).getPort();
674 if (ofPort == OFPort.OFPP_CONTROLLER.getValue()) {
675 salAction = new Controller();
676 } else if (ofPort == OFPort.OFPP_NONE.getValue()) {
677 salAction = new Drop();
678 } else if (ofPort == OFPort.OFPP_IN_PORT.getValue()) {
679 salAction = new Loopback();
680 } else if (ofPort == OFPort.OFPP_FLOOD.getValue()) {
681 salAction = new Flood();
682 } else if (ofPort == OFPort.OFPP_ALL.getValue()) {
683 salAction = new FloodAll();
684 } else if (ofPort == OFPort.OFPP_LOCAL.getValue()) {
685 salAction = new SwPath();
686 } else if (ofPort == OFPort.OFPP_NORMAL.getValue()) {
687 salAction = new HwPath();
688 } else if (ofPort == OFPort.OFPP_TABLE.getValue()) {
689 salAction = new HwPath(); // TODO: we do not handle
690 // table in sal for now
692 salAction = new Output(
693 NodeConnectorCreator.createOFNodeConnector(
696 } else if (ofAction instanceof OFActionEnqueue) {
697 salAction = new Enqueue(NodeConnectorCreator.createOFNodeConnector(
698 ((OFActionEnqueue) ofAction).getPort(), node),
699 ((OFActionEnqueue) ofAction).getQueueId());
700 } else if (ofAction instanceof OFActionVirtualLanIdentifier) {
701 salAction = new SetVlanId(
702 ((OFActionVirtualLanIdentifier) ofAction)
703 .getVirtualLanIdentifier());
704 } else if (ofAction instanceof OFActionStripVirtualLan) {
705 salAction = new PopVlan();
706 } else if (ofAction instanceof OFActionVirtualLanPriorityCodePoint) {
707 salAction = new SetVlanPcp(
708 ((OFActionVirtualLanPriorityCodePoint) ofAction)
709 .getVirtualLanPriorityCodePoint());
710 } else if (ofAction instanceof OFActionDataLayerSource) {
711 salAction = new SetDlSrc(
712 ((OFActionDataLayerSource) ofAction)
713 .getDataLayerAddress().clone());
714 } else if (ofAction instanceof OFActionDataLayerDestination) {
715 salAction = new SetDlDst(
716 ((OFActionDataLayerDestination) ofAction)
717 .getDataLayerAddress().clone());
718 } else if (ofAction instanceof OFActionNetworkLayerSource) {
719 byte addr[] = BigInteger.valueOf(
720 ((OFActionNetworkLayerSource) ofAction)
721 .getNetworkAddress()).toByteArray();
722 InetAddress ip = null;
724 ip = InetAddress.getByAddress(addr);
725 } catch (UnknownHostException e) {
728 salAction = new SetNwSrc(ip);
729 } else if (ofAction instanceof OFActionNetworkLayerDestination) {
730 byte addr[] = BigInteger.valueOf(
731 ((OFActionNetworkLayerDestination) ofAction)
732 .getNetworkAddress()).toByteArray();
733 InetAddress ip = null;
735 ip = InetAddress.getByAddress(addr);
736 } catch (UnknownHostException e) {
739 salAction = new SetNwDst(ip);
740 } else if (ofAction instanceof OFActionNetworkTypeOfService) {
741 salAction = new SetNwTos(
742 ((OFActionNetworkTypeOfService) ofAction)
743 .getNetworkTypeOfService());
744 } else if (ofAction instanceof OFActionTransportLayerSource) {
745 Short port = ((OFActionTransportLayerSource) ofAction)
747 int intPort = NetUtils.getUnsignedShort(port);
748 salAction = new SetTpSrc(intPort);
749 } else if (ofAction instanceof OFActionTransportLayerDestination) {
750 Short port = ((OFActionTransportLayerDestination) ofAction)
752 int intPort = NetUtils.getUnsignedShort(port);
753 salAction = new SetTpDst(intPort);
755 salActionList.add(salAction);
759 flow = new Flow(salMatch, salActionList);
761 logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch,
763 logger.trace("SAL Flow: {}", flow);
767 private static final Map<Integer, Class<? extends Action>> actionMap = new HashMap<Integer, Class<? extends Action>>() {
768 private static final long serialVersionUID = 1L;
770 put(1 << 0, Output.class);
771 put(1 << 1, SetVlanId.class);
772 put(1 << 2, SetVlanPcp.class);
773 put(1 << 3, PopVlan.class);
774 put(1 << 4, SetDlSrc.class);
775 put(1 << 5, SetDlDst.class);
776 put(1 << 6, SetNwSrc.class);
777 put(1 << 7, SetNwDst.class);
778 put(1 << 8, SetNwTos.class);
779 put(1 << 9, SetTpSrc.class);
780 put(1 << 10, SetTpDst.class);
781 put(1 << 11, Enqueue.class);
786 * Returns the supported flow actions for the netwrok node given the bitmask
787 * representing the actions the Openflow 1.0 switch supports
789 * @param ofActionBitmask
790 * OF 1.0 action bitmask
791 * @return The correspondent list of SAL Action classes
793 public static List<Class<? extends Action>> getFlowActions(int ofActionBitmask) {
794 List<Class<? extends Action>> list = new ArrayList<Class<? extends Action>>();
796 for (int i = 0; i < Integer.SIZE; i++) {
798 if ((index & ofActionBitmask) > 0) {
799 if (actionMap.containsKey(index)) {
800 list.add(actionMap.get(index));
804 // Add implicit SAL actions
805 list.add(Controller.class);
806 list.add(SwPath.class);
807 list.add(HwPath.class);
808 list.add(Drop.class);
809 list.add(Flood.class);
810 list.add(FloodAll.class);