summaryrefslogtreecommitdiffstats
path: root/framework/src/onos/providers/openflow/flow/src
diff options
context:
space:
mode:
authorAshlee Young <ashlee@onosfw.com>2015-09-09 22:15:21 -0700
committerAshlee Young <ashlee@onosfw.com>2015-09-09 22:15:21 -0700
commit13d05bc8458758ee39cb829098241e89616717ee (patch)
tree22a4d1ce65f15952f07a3df5af4b462b4697cb3a /framework/src/onos/providers/openflow/flow/src
parent6139282e1e93c2322076de4b91b1c85d0bc4a8b3 (diff)
ONOS checkin based on commit tag e796610b1f721d02f9b0e213cf6f7790c10ecd60
Change-Id: Ife8810491034fe7becdba75dda20de4267bd15cd
Diffstat (limited to 'framework/src/onos/providers/openflow/flow/src')
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java707
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java444
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java230
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java458
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowStatsCollector.java100
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NoMappingFoundException.java31
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java453
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowValueMapper.java152
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/package-info.java20
9 files changed, 2595 insertions, 0 deletions
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
new file mode 100644
index 00000000..f238bdb1
--- /dev/null
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
@@ -0,0 +1,707 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.of.flow.impl;
+
+import static org.onosproject.net.flow.criteria.Criteria.matchLambda;
+import static org.onosproject.net.flow.criteria.Criteria.matchOchSignalType;
+import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupChannelSpacing;
+import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupGridType;
+import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupOchSignalType;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.List;
+
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.Ip6Prefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.TpPort;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.DefaultGroupId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Lambda;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultFlowEntry;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowEntry.FlowEntryState;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.openflow.controller.Dpid;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
+import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
+import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
+import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
+import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.action.OFActionPopMpls;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetField;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetNwDst;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetNwSrc;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanPcp;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanVid;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstructionGotoTable;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteActions;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteMetadata;
+import org.projectfloodlight.openflow.protocol.match.Match;
+import org.projectfloodlight.openflow.protocol.match.MatchField;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigidBasic;
+import org.projectfloodlight.openflow.protocol.ver13.OFFactoryVer13;
+import org.projectfloodlight.openflow.types.CircuitSignalID;
+import org.projectfloodlight.openflow.types.EthType;
+import org.projectfloodlight.openflow.types.IPv4Address;
+import org.projectfloodlight.openflow.types.IPv6Address;
+import org.projectfloodlight.openflow.types.Masked;
+import org.projectfloodlight.openflow.types.OFVlanVidMatch;
+import org.projectfloodlight.openflow.types.TransportPort;
+import org.projectfloodlight.openflow.types.U32;
+import org.projectfloodlight.openflow.types.U64;
+import org.projectfloodlight.openflow.types.U8;
+import org.projectfloodlight.openflow.types.VlanPcp;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Lists;
+
+public class FlowEntryBuilder {
+ private final Logger log = getLogger(getClass());
+
+ private final OFFlowStatsEntry stat;
+ private final OFFlowRemoved removed;
+ private final OFFlowMod flowMod;
+
+ private final Match match;
+
+ // All actions are contained in an OFInstruction. For OF1.0
+ // the instruction type is apply instruction (immediate set in ONOS speak)
+ private final List<OFInstruction> instructions;
+
+ private final Dpid dpid;
+
+ public enum FlowType { STAT, REMOVED, MOD }
+
+ private final FlowType type;
+
+ public FlowEntryBuilder(Dpid dpid, OFFlowStatsEntry entry) {
+ this.stat = entry;
+ this.match = entry.getMatch();
+ this.instructions = getInstructions(entry);
+ this.dpid = dpid;
+ this.removed = null;
+ this.flowMod = null;
+ this.type = FlowType.STAT;
+ }
+
+ public FlowEntryBuilder(Dpid dpid, OFFlowRemoved removed) {
+ this.match = removed.getMatch();
+ this.removed = removed;
+
+ this.dpid = dpid;
+ this.instructions = null;
+ this.stat = null;
+ this.flowMod = null;
+ this.type = FlowType.REMOVED;
+
+ }
+
+ public FlowEntryBuilder(Dpid dpid, OFFlowMod fm) {
+ this.match = fm.getMatch();
+ this.dpid = dpid;
+ this.instructions = getInstructions(fm);
+ this.type = FlowType.MOD;
+ this.flowMod = fm;
+ this.stat = null;
+ this.removed = null;
+ }
+
+ public FlowEntry build(FlowEntryState... state) {
+ FlowRule rule;
+ switch (this.type) {
+ case STAT:
+ rule = DefaultFlowRule.builder()
+ .forDevice(DeviceId.deviceId(Dpid.uri(dpid)))
+ .withSelector(buildSelector())
+ .withTreatment(buildTreatment())
+ .withPriority(stat.getPriority())
+ .makeTemporary(stat.getIdleTimeout())
+ .withCookie(stat.getCookie().getValue())
+ .forTable(stat.getTableId().getValue())
+ .build();
+
+ return new DefaultFlowEntry(rule, FlowEntryState.ADDED,
+ stat.getDurationSec(), stat.getPacketCount().getValue(),
+ stat.getByteCount().getValue());
+ case REMOVED:
+ rule = DefaultFlowRule.builder()
+ .forDevice(DeviceId.deviceId(Dpid.uri(dpid)))
+ .withSelector(buildSelector())
+ .withPriority(removed.getPriority())
+ .makeTemporary(removed.getIdleTimeout())
+ .withCookie(removed.getCookie().getValue())
+ .forTable(removed.getTableId().getValue())
+ .build();
+
+ return new DefaultFlowEntry(rule, FlowEntryState.REMOVED, removed.getDurationSec(),
+ removed.getPacketCount().getValue(), removed.getByteCount().getValue());
+ case MOD:
+ FlowEntryState flowState = state.length > 0 ? state[0] : FlowEntryState.FAILED;
+ rule = DefaultFlowRule.builder()
+ .forDevice(DeviceId.deviceId(Dpid.uri(dpid)))
+ .withSelector(buildSelector())
+ .withTreatment(buildTreatment())
+ .withPriority(flowMod.getPriority())
+ .makeTemporary(flowMod.getIdleTimeout())
+ .withCookie(flowMod.getCookie().getValue())
+ .forTable(flowMod.getTableId().getValue())
+ .build();
+
+ return new DefaultFlowEntry(rule, flowState, 0, 0, 0);
+ default:
+ log.error("Unknown flow type : {}", this.type);
+ return null;
+ }
+
+ }
+
+ private List<OFInstruction> getInstructions(OFFlowMod entry) {
+ switch (entry.getVersion()) {
+ case OF_10:
+ return Lists.newArrayList(OFFactoryVer13.INSTANCE.instructions()
+ .applyActions(
+ entry.getActions()));
+ case OF_11:
+ case OF_12:
+ case OF_13:
+ return entry.getInstructions();
+ default:
+ log.warn("Unknown OF version {}", entry.getVersion());
+ }
+ return Lists.newLinkedList();
+ }
+
+ private List<OFInstruction> getInstructions(OFFlowStatsEntry entry) {
+ switch (entry.getVersion()) {
+ case OF_10:
+ return Lists.newArrayList(
+ OFFactoryVer13.INSTANCE.instructions().applyActions(entry.getActions()));
+ case OF_11:
+ case OF_12:
+ case OF_13:
+ return entry.getInstructions();
+ default:
+ log.warn("Unknown OF version {}", entry.getVersion());
+ }
+ return Lists.newLinkedList();
+ }
+
+ private TrafficTreatment buildTreatment() {
+ TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
+ // If this is a drop rule
+ if (instructions.size() == 0) {
+ builder.drop();
+ return builder.build();
+ }
+ for (OFInstruction in : instructions) {
+ switch (in.getType()) {
+ case GOTO_TABLE:
+ builder.transition(((int) ((OFInstructionGotoTable) in)
+ .getTableId().getValue()));
+ break;
+ case WRITE_METADATA:
+ OFInstructionWriteMetadata m = (OFInstructionWriteMetadata) in;
+ builder.writeMetadata(m.getMetadata().getValue(),
+ m.getMetadataMask().getValue());
+ break;
+ case WRITE_ACTIONS:
+ builder.deferred();
+ buildActions(((OFInstructionWriteActions) in).getActions(),
+ builder);
+ break;
+ case APPLY_ACTIONS:
+ builder.immediate();
+ buildActions(((OFInstructionApplyActions) in).getActions(),
+ builder);
+ break;
+ case CLEAR_ACTIONS:
+ builder.wipeDeferred();
+ break;
+ case EXPERIMENTER:
+ break;
+ case METER:
+ break;
+ default:
+ log.warn("Unknown instructions type {}", in.getType());
+ }
+ }
+
+ return builder.build();
+ }
+
+ private TrafficTreatment.Builder buildActions(List<OFAction> actions,
+ TrafficTreatment.Builder builder) {
+ for (OFAction act : actions) {
+ switch (act.getType()) {
+ case OUTPUT:
+ OFActionOutput out = (OFActionOutput) act;
+ builder.setOutput(
+ PortNumber.portNumber(out.getPort().getPortNumber()));
+ break;
+ case SET_VLAN_VID:
+ OFActionSetVlanVid vlan = (OFActionSetVlanVid) act;
+ builder.setVlanId(VlanId.vlanId(vlan.getVlanVid().getVlan()));
+ break;
+ case SET_VLAN_PCP:
+ OFActionSetVlanPcp pcp = (OFActionSetVlanPcp) act;
+ builder.setVlanPcp(pcp.getVlanPcp().getValue());
+ break;
+ case SET_DL_DST:
+ OFActionSetDlDst dldst = (OFActionSetDlDst) act;
+ builder.setEthDst(
+ MacAddress.valueOf(dldst.getDlAddr().getLong()));
+ break;
+ case SET_DL_SRC:
+ OFActionSetDlSrc dlsrc = (OFActionSetDlSrc) act;
+ builder.setEthSrc(
+ MacAddress.valueOf(dlsrc.getDlAddr().getLong()));
+
+ break;
+ case SET_NW_DST:
+ OFActionSetNwDst nwdst = (OFActionSetNwDst) act;
+ IPv4Address di = nwdst.getNwAddr();
+ builder.setIpDst(Ip4Address.valueOf(di.getInt()));
+ break;
+ case SET_NW_SRC:
+ OFActionSetNwSrc nwsrc = (OFActionSetNwSrc) act;
+ IPv4Address si = nwsrc.getNwAddr();
+ builder.setIpSrc(Ip4Address.valueOf(si.getInt()));
+ break;
+ case EXPERIMENTER:
+ OFActionExperimenter exp = (OFActionExperimenter) act;
+ if (exp.getExperimenter() == 0x80005A06 ||
+ exp.getExperimenter() == 0x748771) {
+ OFActionCircuit ct = (OFActionCircuit) exp;
+ short lambda = ((OFOxmOchSigidBasic) ct.getField()).getValue().getChannelNumber();
+ builder.add(Instructions.modL0Lambda(Lambda.indexedLambda(lambda)));
+ } else {
+ log.warn("Unsupported OFActionExperimenter {}", exp.getExperimenter());
+ }
+ break;
+ case SET_FIELD:
+ OFActionSetField setField = (OFActionSetField) act;
+ handleSetField(builder, setField.getField());
+ break;
+ case POP_MPLS:
+ OFActionPopMpls popMpls = (OFActionPopMpls) act;
+ builder.popMpls((short) popMpls.getEthertype().getValue());
+ break;
+ case PUSH_MPLS:
+ builder.pushMpls();
+ break;
+ case COPY_TTL_IN:
+ builder.copyTtlIn();
+ break;
+ case COPY_TTL_OUT:
+ builder.copyTtlOut();
+ break;
+ case DEC_MPLS_TTL:
+ builder.decMplsTtl();
+ break;
+ case DEC_NW_TTL:
+ builder.decNwTtl();
+ break;
+ case GROUP:
+ OFActionGroup group = (OFActionGroup) act;
+ builder.group(new DefaultGroupId(group.getGroup().getGroupNumber()));
+ break;
+ case STRIP_VLAN:
+ case POP_VLAN:
+ builder.popVlan();
+ break;
+ case PUSH_VLAN:
+ builder.pushVlan();
+ break;
+ case SET_TP_DST:
+ case SET_TP_SRC:
+ case POP_PBB:
+ case PUSH_PBB:
+ case SET_MPLS_LABEL:
+ case SET_MPLS_TC:
+ case SET_MPLS_TTL:
+ case SET_NW_ECN:
+ case SET_NW_TOS:
+ case SET_NW_TTL:
+ case SET_QUEUE:
+
+ case ENQUEUE:
+ default:
+ log.warn("Action type {} not yet implemented.", act.getType());
+ }
+ }
+ return builder;
+ }
+
+
+ private void handleSetField(TrafficTreatment.Builder builder, OFOxm<?> oxm) {
+ switch (oxm.getMatchField().id) {
+ case VLAN_PCP:
+ @SuppressWarnings("unchecked")
+ OFOxm<VlanPcp> vlanpcp = (OFOxm<VlanPcp>) oxm;
+ builder.setVlanPcp(vlanpcp.getValue().getValue());
+ break;
+ case VLAN_VID:
+ @SuppressWarnings("unchecked")
+ OFOxm<OFVlanVidMatch> vlanvid = (OFOxm<OFVlanVidMatch>) oxm;
+ builder.setVlanId(VlanId.vlanId(vlanvid.getValue().getVlan()));
+ break;
+ case ETH_DST:
+ @SuppressWarnings("unchecked")
+ OFOxm<org.projectfloodlight.openflow.types.MacAddress> ethdst =
+ (OFOxm<org.projectfloodlight.openflow.types.MacAddress>) oxm;
+ builder.setEthDst(MacAddress.valueOf(ethdst.getValue().getLong()));
+ break;
+ case ETH_SRC:
+ @SuppressWarnings("unchecked")
+ OFOxm<org.projectfloodlight.openflow.types.MacAddress> ethsrc =
+ (OFOxm<org.projectfloodlight.openflow.types.MacAddress>) oxm;
+ builder.setEthSrc(MacAddress.valueOf(ethsrc.getValue().getLong()));
+ break;
+ case IPV4_DST:
+ @SuppressWarnings("unchecked")
+ OFOxm<IPv4Address> ip4dst = (OFOxm<IPv4Address>) oxm;
+ builder.setIpDst(Ip4Address.valueOf(ip4dst.getValue().getInt()));
+ break;
+ case IPV4_SRC:
+ @SuppressWarnings("unchecked")
+ OFOxm<IPv4Address> ip4src = (OFOxm<IPv4Address>) oxm;
+ builder.setIpSrc(Ip4Address.valueOf(ip4src.getValue().getInt()));
+ break;
+ case MPLS_LABEL:
+ @SuppressWarnings("unchecked")
+ OFOxm<U32> labelId = (OFOxm<U32>) oxm;
+ builder.setMpls(MplsLabel.mplsLabel((int) labelId.getValue().getValue()));
+ break;
+ case MPLS_BOS:
+ @SuppressWarnings("unchecked")
+ OFOxm<U8> mplsBos = (OFOxm<U8>) oxm;
+ builder.setMplsBos(mplsBos.getValue() == U8.ZERO ? false : true);
+ break;
+ case TUNNEL_ID:
+ @SuppressWarnings("unchecked")
+ OFOxm<U64> tunnelId = (OFOxm<U64>) oxm;
+ builder.setTunnelId(tunnelId.getValue().getValue());
+ break;
+ case TCP_DST:
+ @SuppressWarnings("unchecked")
+ OFOxm<TransportPort> tcpdst = (OFOxm<TransportPort>) oxm;
+ builder.setTcpDst(TpPort.tpPort(tcpdst.getValue().getPort()));
+ break;
+ case TCP_SRC:
+ @SuppressWarnings("unchecked")
+ OFOxm<TransportPort> tcpsrc = (OFOxm<TransportPort>) oxm;
+ builder.setTcpSrc(TpPort.tpPort(tcpsrc.getValue().getPort()));
+ break;
+ case UDP_DST:
+ @SuppressWarnings("unchecked")
+ OFOxm<TransportPort> udpdst = (OFOxm<TransportPort>) oxm;
+ builder.setUdpDst(TpPort.tpPort(udpdst.getValue().getPort()));
+ break;
+ case UDP_SRC:
+ @SuppressWarnings("unchecked")
+ OFOxm<TransportPort> udpsrc = (OFOxm<TransportPort>) oxm;
+ builder.setUdpSrc(TpPort.tpPort(udpsrc.getValue().getPort()));
+ break;
+ case ARP_OP:
+ case ARP_SHA:
+ case ARP_SPA:
+ case ARP_THA:
+ case ARP_TPA:
+ case BSN_EGR_PORT_GROUP_ID:
+ case BSN_GLOBAL_VRF_ALLOWED:
+ case BSN_IN_PORTS_128:
+ case BSN_L3_DST_CLASS_ID:
+ case BSN_L3_INTERFACE_CLASS_ID:
+ case BSN_L3_SRC_CLASS_ID:
+ case BSN_LAG_ID:
+ case BSN_TCP_FLAGS:
+ case BSN_UDF0:
+ case BSN_UDF1:
+ case BSN_UDF2:
+ case BSN_UDF3:
+ case BSN_UDF4:
+ case BSN_UDF5:
+ case BSN_UDF6:
+ case BSN_UDF7:
+ case BSN_VLAN_XLATE_PORT_GROUP_ID:
+ case BSN_VRF:
+ case ETH_TYPE:
+ case ICMPV4_CODE:
+ case ICMPV4_TYPE:
+ case ICMPV6_CODE:
+ case ICMPV6_TYPE:
+ case IN_PHY_PORT:
+ case IN_PORT:
+ case IPV6_DST:
+ case IPV6_FLABEL:
+ case IPV6_ND_SLL:
+ case IPV6_ND_TARGET:
+ case IPV6_ND_TLL:
+ case IPV6_SRC:
+ case IP_DSCP:
+ case IP_ECN:
+ case IP_PROTO:
+ case METADATA:
+ case MPLS_TC:
+ case OCH_SIGID:
+ case OCH_SIGID_BASIC:
+ case OCH_SIGTYPE:
+ case OCH_SIGTYPE_BASIC:
+ case SCTP_DST:
+ case SCTP_SRC:
+ default:
+ log.warn("Set field type {} not yet implemented.", oxm.getMatchField().id);
+ break;
+ }
+ }
+
+ // CHECKSTYLE IGNORE MethodLength FOR NEXT 1 LINES
+ private TrafficSelector buildSelector() {
+ MacAddress mac;
+ Ip4Prefix ip4Prefix;
+ Ip6Address ip6Address;
+ Ip6Prefix ip6Prefix;
+
+ TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
+ for (MatchField<?> field : match.getMatchFields()) {
+ switch (field.id) {
+ case IN_PORT:
+ builder.matchInPort(PortNumber
+ .portNumber(match.get(MatchField.IN_PORT).getPortNumber()));
+ break;
+ case IN_PHY_PORT:
+ builder.matchInPhyPort(PortNumber
+ .portNumber(match.get(MatchField.IN_PHY_PORT).getPortNumber()));
+ break;
+ case METADATA:
+ long metadata =
+ match.get(MatchField.METADATA).getValue().getValue();
+ builder.matchMetadata(metadata);
+ break;
+ case ETH_DST:
+ mac = MacAddress.valueOf(match.get(MatchField.ETH_DST).getLong());
+ builder.matchEthDst(mac);
+ break;
+ case ETH_SRC:
+ mac = MacAddress.valueOf(match.get(MatchField.ETH_SRC).getLong());
+ builder.matchEthSrc(mac);
+ break;
+ case ETH_TYPE:
+ int ethType = match.get(MatchField.ETH_TYPE).getValue();
+ if (ethType == EthType.VLAN_FRAME.getValue()) {
+ builder.matchVlanId(VlanId.ANY);
+ } else {
+ builder.matchEthType((short) ethType);
+ }
+ break;
+ case VLAN_VID:
+ VlanId vlanId = null;
+ if (match.isPartiallyMasked(MatchField.VLAN_VID)) {
+ Masked<OFVlanVidMatch> masked = match.getMasked(MatchField.VLAN_VID);
+ if (masked.getValue().equals(OFVlanVidMatch.PRESENT)
+ && masked.getMask().equals(OFVlanVidMatch.PRESENT)) {
+ vlanId = VlanId.ANY;
+ }
+ } else {
+ if (!match.get(MatchField.VLAN_VID).isPresentBitSet()) {
+ vlanId = VlanId.NONE;
+ } else {
+ vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan());
+ }
+ }
+ if (vlanId != null) {
+ builder.matchVlanId(vlanId);
+ }
+ break;
+ case VLAN_PCP:
+ byte vlanPcp = match.get(MatchField.VLAN_PCP).getValue();
+ builder.matchVlanPcp(vlanPcp);
+ break;
+ case IP_DSCP:
+ byte ipDscp = match.get(MatchField.IP_DSCP).getDscpValue();
+ builder.matchIPDscp(ipDscp);
+ break;
+ case IP_ECN:
+ byte ipEcn = match.get(MatchField.IP_ECN).getEcnValue();
+ builder.matchIPEcn(ipEcn);
+ break;
+ case IP_PROTO:
+ short proto = match.get(MatchField.IP_PROTO).getIpProtocolNumber();
+ builder.matchIPProtocol((byte) proto);
+ break;
+ case IPV4_SRC:
+ if (match.isPartiallyMasked(MatchField.IPV4_SRC)) {
+ Masked<IPv4Address> maskedIp = match.getMasked(MatchField.IPV4_SRC);
+ ip4Prefix = Ip4Prefix.valueOf(
+ maskedIp.getValue().getInt(),
+ maskedIp.getMask().asCidrMaskLength());
+ } else {
+ ip4Prefix = Ip4Prefix.valueOf(
+ match.get(MatchField.IPV4_SRC).getInt(),
+ Ip4Prefix.MAX_MASK_LENGTH);
+ }
+ builder.matchIPSrc(ip4Prefix);
+ break;
+ case IPV4_DST:
+ if (match.isPartiallyMasked(MatchField.IPV4_DST)) {
+ Masked<IPv4Address> maskedIp = match.getMasked(MatchField.IPV4_DST);
+ ip4Prefix = Ip4Prefix.valueOf(
+ maskedIp.getValue().getInt(),
+ maskedIp.getMask().asCidrMaskLength());
+ } else {
+ ip4Prefix = Ip4Prefix.valueOf(
+ match.get(MatchField.IPV4_DST).getInt(),
+ Ip4Prefix.MAX_MASK_LENGTH);
+ }
+ builder.matchIPDst(ip4Prefix);
+ break;
+ case TCP_SRC:
+ builder.matchTcpSrc(TpPort.tpPort(match.get(MatchField.TCP_SRC).getPort()));
+ break;
+ case TCP_DST:
+ builder.matchTcpDst(TpPort.tpPort(match.get(MatchField.TCP_DST).getPort()));
+ break;
+ case UDP_SRC:
+ builder.matchUdpSrc(TpPort.tpPort(match.get(MatchField.UDP_SRC).getPort()));
+ break;
+ case UDP_DST:
+ builder.matchUdpDst(TpPort.tpPort(match.get(MatchField.UDP_DST).getPort()));
+ break;
+ case MPLS_LABEL:
+ builder.matchMplsLabel(MplsLabel.mplsLabel((int) match.get(MatchField.MPLS_LABEL)
+ .getValue()));
+ break;
+ case MPLS_BOS:
+ builder.matchMplsBos(match.get(MatchField.MPLS_BOS).getValue());
+ break;
+ case SCTP_SRC:
+ builder.matchSctpSrc(TpPort.tpPort(match.get(MatchField.SCTP_SRC).getPort()));
+ break;
+ case SCTP_DST:
+ builder.matchSctpDst(TpPort.tpPort(match.get(MatchField.SCTP_DST).getPort()));
+ break;
+ case ICMPV4_TYPE:
+ byte icmpType = (byte) match.get(MatchField.ICMPV4_TYPE).getType();
+ builder.matchIcmpType(icmpType);
+ break;
+ case ICMPV4_CODE:
+ byte icmpCode = (byte) match.get(MatchField.ICMPV4_CODE).getCode();
+ builder.matchIcmpCode(icmpCode);
+ break;
+ case IPV6_SRC:
+ if (match.isPartiallyMasked(MatchField.IPV6_SRC)) {
+ Masked<IPv6Address> maskedIp = match.getMasked(MatchField.IPV6_SRC);
+ ip6Prefix = Ip6Prefix.valueOf(
+ maskedIp.getValue().getBytes(),
+ maskedIp.getMask().asCidrMaskLength());
+ } else {
+ ip6Prefix = Ip6Prefix.valueOf(
+ match.get(MatchField.IPV6_SRC).getBytes(),
+ Ip6Prefix.MAX_MASK_LENGTH);
+ }
+ builder.matchIPv6Src(ip6Prefix);
+ break;
+ case IPV6_DST:
+ if (match.isPartiallyMasked(MatchField.IPV6_DST)) {
+ Masked<IPv6Address> maskedIp = match.getMasked(MatchField.IPV6_DST);
+ ip6Prefix = Ip6Prefix.valueOf(
+ maskedIp.getValue().getBytes(),
+ maskedIp.getMask().asCidrMaskLength());
+ } else {
+ ip6Prefix = Ip6Prefix.valueOf(
+ match.get(MatchField.IPV6_DST).getBytes(),
+ Ip6Prefix.MAX_MASK_LENGTH);
+ }
+ builder.matchIPv6Dst(ip6Prefix);
+ break;
+ case IPV6_FLABEL:
+ int flowLabel =
+ match.get(MatchField.IPV6_FLABEL).getIPv6FlowLabelValue();
+ builder.matchIPv6FlowLabel(flowLabel);
+ break;
+ case ICMPV6_TYPE:
+ byte icmpv6type = (byte) match.get(MatchField.ICMPV6_TYPE).getValue();
+ builder.matchIcmpv6Type(icmpv6type);
+ break;
+ case ICMPV6_CODE:
+ byte icmpv6code = (byte) match.get(MatchField.ICMPV6_CODE).getValue();
+ builder.matchIcmpv6Code(icmpv6code);
+ break;
+ case IPV6_ND_TARGET:
+ ip6Address =
+ Ip6Address.valueOf(match.get(MatchField.IPV6_ND_TARGET).getBytes());
+ builder.matchIPv6NDTargetAddress(ip6Address);
+ break;
+ case IPV6_ND_SLL:
+ mac = MacAddress.valueOf(match.get(MatchField.IPV6_ND_SLL).getLong());
+ builder.matchIPv6NDSourceLinkLayerAddress(mac);
+ break;
+ case IPV6_ND_TLL:
+ mac = MacAddress.valueOf(match.get(MatchField.IPV6_ND_TLL).getLong());
+ builder.matchIPv6NDTargetLinkLayerAddress(mac);
+ break;
+ case IPV6_EXTHDR:
+ builder.matchIPv6ExthdrFlags((short) match.get(MatchField.IPV6_EXTHDR)
+ .getValue());
+ break;
+ case OCH_SIGID:
+ CircuitSignalID sigId = match.get(MatchField.OCH_SIGID);
+ builder.add(matchLambda(Lambda.ochSignal(
+ lookupGridType(sigId.getGridType()), lookupChannelSpacing(sigId.getChannelSpacing()),
+ sigId.getChannelNumber(), sigId.getSpectralWidth())
+ ));
+ break;
+ case OCH_SIGTYPE:
+ U8 sigType = match.get(MatchField.OCH_SIGTYPE);
+ builder.add(matchOchSignalType(lookupOchSignalType((byte) sigType.getValue())));
+ break;
+ case TUNNEL_ID:
+ long tunnelId = match.get(MatchField.TUNNEL_ID).getValue();
+ builder.matchTunnelId(tunnelId);
+ break;
+ case ARP_OP:
+ case ARP_SHA:
+ case ARP_SPA:
+ case ARP_THA:
+ case ARP_TPA:
+ case MPLS_TC:
+ default:
+ log.warn("Match type {} not yet implemented.", field.id);
+ }
+ }
+ return builder.build();
+ }
+}
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java
new file mode 100644
index 00000000..e050524a
--- /dev/null
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java
@@ -0,0 +1,444 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.of.flow.impl;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Optional;
+
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.Ip6Prefix;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.EthCriterion;
+import org.onosproject.net.flow.criteria.EthTypeCriterion;
+import org.onosproject.net.flow.criteria.IPCriterion;
+import org.onosproject.net.flow.criteria.IPDscpCriterion;
+import org.onosproject.net.flow.criteria.IPEcnCriterion;
+import org.onosproject.net.flow.criteria.IPProtocolCriterion;
+import org.onosproject.net.flow.criteria.IPv6ExthdrFlagsCriterion;
+import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
+import org.onosproject.net.flow.criteria.IPv6NDLinkLayerAddressCriterion;
+import org.onosproject.net.flow.criteria.IPv6NDTargetAddressCriterion;
+import org.onosproject.net.flow.criteria.IcmpCodeCriterion;
+import org.onosproject.net.flow.criteria.IcmpTypeCriterion;
+import org.onosproject.net.flow.criteria.Icmpv6CodeCriterion;
+import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
+import org.onosproject.net.flow.criteria.MetadataCriterion;
+import org.onosproject.net.flow.criteria.MplsBosCriterion;
+import org.onosproject.net.flow.criteria.MplsCriterion;
+import org.onosproject.net.flow.criteria.OchSignalCriterion;
+import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.criteria.SctpPortCriterion;
+import org.onosproject.net.flow.criteria.TcpPortCriterion;
+import org.onosproject.net.flow.criteria.TunnelIdCriterion;
+import org.onosproject.net.flow.criteria.UdpPortCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flow.criteria.VlanPcpCriterion;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFFlowAdd;
+import org.projectfloodlight.openflow.protocol.OFFlowDelete;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.match.Match;
+import org.projectfloodlight.openflow.protocol.match.MatchField;
+import org.projectfloodlight.openflow.types.CircuitSignalID;
+import org.projectfloodlight.openflow.types.EthType;
+import org.projectfloodlight.openflow.types.ICMPv4Code;
+import org.projectfloodlight.openflow.types.ICMPv4Type;
+import org.projectfloodlight.openflow.types.IPv4Address;
+import org.projectfloodlight.openflow.types.IPv6Address;
+import org.projectfloodlight.openflow.types.IPv6FlowLabel;
+import org.projectfloodlight.openflow.types.IpDscp;
+import org.projectfloodlight.openflow.types.IpEcn;
+import org.projectfloodlight.openflow.types.IpProtocol;
+import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.types.Masked;
+import org.projectfloodlight.openflow.types.OFBooleanValue;
+import org.projectfloodlight.openflow.types.OFMetadata;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.OFVlanVidMatch;
+import org.projectfloodlight.openflow.types.TransportPort;
+import org.projectfloodlight.openflow.types.U16;
+import org.projectfloodlight.openflow.types.U32;
+import org.projectfloodlight.openflow.types.U64;
+import org.projectfloodlight.openflow.types.U8;
+import org.projectfloodlight.openflow.types.VlanPcp;
+import org.projectfloodlight.openflow.types.VlanVid;
+import org.slf4j.Logger;
+
+/**
+ * Builder for OpenFlow flow mods based on FlowRules.
+ */
+public abstract class FlowModBuilder {
+
+ private final Logger log = getLogger(getClass());
+
+ private final OFFactory factory;
+ private final FlowRule flowRule;
+ private final TrafficSelector selector;
+ protected final Long xid;
+
+ /**
+ * Creates a new flow mod builder.
+ *
+ * @param flowRule the flow rule to transform into a flow mod
+ * @param factory the OpenFlow factory to use to build the flow mod
+ * @param xid the transaction ID
+ * @return the new flow mod builder
+ */
+ public static FlowModBuilder builder(FlowRule flowRule,
+ OFFactory factory,
+ Optional<Long> xid) {
+ switch (factory.getVersion()) {
+ case OF_10:
+ return new FlowModBuilderVer10(flowRule, factory, xid);
+ case OF_13:
+ return new FlowModBuilderVer13(flowRule, factory, xid);
+ default:
+ throw new UnsupportedOperationException(
+ "No flow mod builder for protocol version " + factory.getVersion());
+ }
+ }
+
+ /**
+ * Constructs a flow mod builder.
+ *
+ * @param flowRule the flow rule to transform into a flow mod
+ * @param factory the OpenFlow factory to use to build the flow mod
+ * @param xid the transaction ID
+ */
+ protected FlowModBuilder(FlowRule flowRule, OFFactory factory, Optional<Long> xid) {
+ this.factory = factory;
+ this.flowRule = flowRule;
+ this.selector = flowRule.selector();
+ this.xid = xid.orElse(0L);
+
+ }
+
+ /**
+ * Builds an ADD flow mod.
+ *
+ * @return the flow mod
+ */
+ public abstract OFFlowAdd buildFlowAdd();
+
+ /**
+ * Builds a MODIFY flow mod.
+ *
+ * @return the flow mod
+ */
+ public abstract OFFlowMod buildFlowMod();
+
+ /**
+ * Builds a DELETE flow mod.
+ *
+ * @return the flow mod
+ */
+ public abstract OFFlowDelete buildFlowDel();
+
+ /**
+ * Builds the match for the flow mod.
+ *
+ * @return the match
+ */
+ // CHECKSTYLE IGNORE MethodLength FOR NEXT 300 LINES
+ protected Match buildMatch() {
+ Match.Builder mBuilder = factory.buildMatch();
+ Ip6Address ip6Address;
+ Ip4Prefix ip4Prefix;
+ Ip6Prefix ip6Prefix;
+ EthCriterion ethCriterion;
+ IPCriterion ipCriterion;
+ TcpPortCriterion tcpPortCriterion;
+ UdpPortCriterion udpPortCriterion;
+ SctpPortCriterion sctpPortCriterion;
+ IPv6NDLinkLayerAddressCriterion llAddressCriterion;
+
+ for (Criterion c : selector.criteria()) {
+ switch (c.type()) {
+ case IN_PORT:
+ PortCriterion inPort = (PortCriterion) c;
+ mBuilder.setExact(MatchField.IN_PORT,
+ OFPort.of((int) inPort.port().toLong()));
+ break;
+ case IN_PHY_PORT:
+ PortCriterion inPhyPort = (PortCriterion) c;
+ mBuilder.setExact(MatchField.IN_PORT,
+ OFPort.of((int) inPhyPort.port().toLong()));
+ break;
+ case METADATA:
+ MetadataCriterion metadata = (MetadataCriterion) c;
+ mBuilder.setExact(MatchField.METADATA,
+ OFMetadata.ofRaw(metadata.metadata()));
+ break;
+ case ETH_DST:
+ ethCriterion = (EthCriterion) c;
+ mBuilder.setExact(MatchField.ETH_DST,
+ MacAddress.of(ethCriterion.mac().toLong()));
+ break;
+ case ETH_SRC:
+ ethCriterion = (EthCriterion) c;
+ mBuilder.setExact(MatchField.ETH_SRC,
+ MacAddress.of(ethCriterion.mac().toLong()));
+ break;
+ case ETH_TYPE:
+ EthTypeCriterion ethType = (EthTypeCriterion) c;
+ mBuilder.setExact(MatchField.ETH_TYPE, EthType.of(ethType.ethType().toShort()));
+ break;
+ case VLAN_VID:
+ VlanIdCriterion vid = (VlanIdCriterion) c;
+
+ if (vid.vlanId().equals(VlanId.ANY)) {
+ mBuilder.setMasked(MatchField.VLAN_VID, OFVlanVidMatch.PRESENT,
+ OFVlanVidMatch.PRESENT);
+ } else if (vid.vlanId().equals(VlanId.NONE)) {
+ mBuilder.setExact(MatchField.VLAN_VID, OFVlanVidMatch.NONE);
+ } else {
+ mBuilder.setExact(MatchField.VLAN_VID,
+ OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vid.vlanId().toShort())));
+ }
+ break;
+ case VLAN_PCP:
+ VlanPcpCriterion vpcp = (VlanPcpCriterion) c;
+ mBuilder.setExact(MatchField.VLAN_PCP, VlanPcp.of(vpcp.priority()));
+ break;
+ case IP_DSCP:
+ IPDscpCriterion ipDscpCriterion = (IPDscpCriterion) c;
+ mBuilder.setExact(MatchField.IP_DSCP,
+ IpDscp.of(ipDscpCriterion.ipDscp()));
+ break;
+ case IP_ECN:
+ IPEcnCriterion ipEcnCriterion = (IPEcnCriterion) c;
+ mBuilder.setExact(MatchField.IP_ECN,
+ IpEcn.of(ipEcnCriterion.ipEcn()));
+ break;
+ case IP_PROTO:
+ IPProtocolCriterion p = (IPProtocolCriterion) c;
+ mBuilder.setExact(MatchField.IP_PROTO, IpProtocol.of(p.protocol()));
+ break;
+ case IPV4_SRC:
+ ipCriterion = (IPCriterion) c;
+ ip4Prefix = ipCriterion.ip().getIp4Prefix();
+ if (ip4Prefix.prefixLength() != Ip4Prefix.MAX_MASK_LENGTH) {
+ Ip4Address maskAddr =
+ Ip4Address.makeMaskPrefix(ip4Prefix.prefixLength());
+ Masked<IPv4Address> maskedIp =
+ Masked.of(IPv4Address.of(ip4Prefix.address().toInt()),
+ IPv4Address.of(maskAddr.toInt()));
+ mBuilder.setMasked(MatchField.IPV4_SRC, maskedIp);
+ } else {
+ mBuilder.setExact(MatchField.IPV4_SRC,
+ IPv4Address.of(ip4Prefix.address().toInt()));
+ }
+ break;
+ case IPV4_DST:
+ ipCriterion = (IPCriterion) c;
+ ip4Prefix = ipCriterion.ip().getIp4Prefix();
+ if (ip4Prefix.prefixLength() != Ip4Prefix.MAX_MASK_LENGTH) {
+ Ip4Address maskAddr =
+ Ip4Address.makeMaskPrefix(ip4Prefix.prefixLength());
+ Masked<IPv4Address> maskedIp =
+ Masked.of(IPv4Address.of(ip4Prefix.address().toInt()),
+ IPv4Address.of(maskAddr.toInt()));
+ mBuilder.setMasked(MatchField.IPV4_DST, maskedIp);
+ } else {
+ mBuilder.setExact(MatchField.IPV4_DST,
+ IPv4Address.of(ip4Prefix.address().toInt()));
+ }
+ break;
+ case TCP_SRC:
+ tcpPortCriterion = (TcpPortCriterion) c;
+ mBuilder.setExact(MatchField.TCP_SRC,
+ TransportPort.of(tcpPortCriterion.tcpPort().toInt()));
+ break;
+ case TCP_DST:
+ tcpPortCriterion = (TcpPortCriterion) c;
+ mBuilder.setExact(MatchField.TCP_DST,
+ TransportPort.of(tcpPortCriterion.tcpPort().toInt()));
+ break;
+ case UDP_SRC:
+ udpPortCriterion = (UdpPortCriterion) c;
+ mBuilder.setExact(MatchField.UDP_SRC,
+ TransportPort.of(udpPortCriterion.udpPort().toInt()));
+ break;
+ case UDP_DST:
+ udpPortCriterion = (UdpPortCriterion) c;
+ mBuilder.setExact(MatchField.UDP_DST,
+ TransportPort.of(udpPortCriterion.udpPort().toInt()));
+ break;
+ case SCTP_SRC:
+ sctpPortCriterion = (SctpPortCriterion) c;
+ mBuilder.setExact(MatchField.SCTP_SRC,
+ TransportPort.of(sctpPortCriterion.sctpPort().toInt()));
+ break;
+ case SCTP_DST:
+ sctpPortCriterion = (SctpPortCriterion) c;
+ mBuilder.setExact(MatchField.SCTP_DST,
+ TransportPort.of(sctpPortCriterion.sctpPort().toInt()));
+ break;
+ case ICMPV4_TYPE:
+ IcmpTypeCriterion icmpType = (IcmpTypeCriterion) c;
+ mBuilder.setExact(MatchField.ICMPV4_TYPE,
+ ICMPv4Type.of(icmpType.icmpType()));
+ break;
+ case ICMPV4_CODE:
+ IcmpCodeCriterion icmpCode = (IcmpCodeCriterion) c;
+ mBuilder.setExact(MatchField.ICMPV4_CODE,
+ ICMPv4Code.of(icmpCode.icmpCode()));
+ break;
+ case IPV6_SRC:
+ ipCriterion = (IPCriterion) c;
+ ip6Prefix = ipCriterion.ip().getIp6Prefix();
+ if (ip6Prefix.prefixLength() != Ip6Prefix.MAX_MASK_LENGTH) {
+ Ip6Address maskAddr =
+ Ip6Address.makeMaskPrefix(ip6Prefix.prefixLength());
+ Masked<IPv6Address> maskedIp =
+ Masked.of(IPv6Address.of(ip6Prefix.address().toString()),
+ IPv6Address.of(maskAddr.toString()));
+ mBuilder.setMasked(MatchField.IPV6_SRC, maskedIp);
+ } else {
+ mBuilder.setExact(MatchField.IPV6_SRC,
+ IPv6Address.of(ip6Prefix.address().toString()));
+ }
+ break;
+ case IPV6_DST:
+ ipCriterion = (IPCriterion) c;
+ ip6Prefix = ipCriterion.ip().getIp6Prefix();
+ if (ip6Prefix.prefixLength() != Ip6Prefix.MAX_MASK_LENGTH) {
+ Ip6Address maskAddr =
+ Ip6Address.makeMaskPrefix(ip6Prefix.prefixLength());
+ Masked<IPv6Address> maskedIp =
+ Masked.of(IPv6Address.of(ip6Prefix.address().toString()),
+ IPv6Address.of(maskAddr.toString()));
+ mBuilder.setMasked(MatchField.IPV6_DST, maskedIp);
+ } else {
+ mBuilder.setExact(MatchField.IPV6_DST,
+ IPv6Address.of(ip6Prefix.address().toString()));
+ }
+ break;
+ case IPV6_FLABEL:
+ IPv6FlowLabelCriterion flowLabelCriterion =
+ (IPv6FlowLabelCriterion) c;
+ mBuilder.setExact(MatchField.IPV6_FLABEL,
+ IPv6FlowLabel.of(flowLabelCriterion.flowLabel()));
+ break;
+ case ICMPV6_TYPE:
+ Icmpv6TypeCriterion icmpv6Type = (Icmpv6TypeCriterion) c;
+ mBuilder.setExact(MatchField.ICMPV6_TYPE,
+ U8.of(icmpv6Type.icmpv6Type()));
+ break;
+ case ICMPV6_CODE:
+ Icmpv6CodeCriterion icmpv6Code = (Icmpv6CodeCriterion) c;
+ mBuilder.setExact(MatchField.ICMPV6_CODE,
+ U8.of(icmpv6Code.icmpv6Code()));
+ break;
+ case IPV6_ND_TARGET:
+ IPv6NDTargetAddressCriterion targetAddressCriterion =
+ (IPv6NDTargetAddressCriterion) c;
+ ip6Address = targetAddressCriterion.targetAddress();
+ mBuilder.setExact(MatchField.IPV6_ND_TARGET,
+ IPv6Address.of(ip6Address.toOctets()));
+ break;
+ case IPV6_ND_SLL:
+ llAddressCriterion =
+ (IPv6NDLinkLayerAddressCriterion) c;
+ mBuilder.setExact(MatchField.IPV6_ND_SLL,
+ MacAddress.of(llAddressCriterion.mac().toLong()));
+ break;
+ case IPV6_ND_TLL:
+ llAddressCriterion =
+ (IPv6NDLinkLayerAddressCriterion) c;
+ mBuilder.setExact(MatchField.IPV6_ND_TLL,
+ MacAddress.of(llAddressCriterion.mac().toLong()));
+ break;
+ case MPLS_LABEL:
+ MplsCriterion mp = (MplsCriterion) c;
+ mBuilder.setExact(MatchField.MPLS_LABEL, U32.of(mp.label().toInt()));
+ break;
+ case IPV6_EXTHDR:
+ IPv6ExthdrFlagsCriterion exthdrFlagsCriterion =
+ (IPv6ExthdrFlagsCriterion) c;
+ mBuilder.setExact(MatchField.IPV6_EXTHDR,
+ U16.of(exthdrFlagsCriterion.exthdrFlags()));
+ break;
+ case OCH_SIGID:
+ try {
+ OchSignalCriterion ochSignalCriterion = (OchSignalCriterion) c;
+ OchSignal signal = ochSignalCriterion.lambda();
+ byte gridType = OpenFlowValueMapper.lookupGridType(signal.gridType());
+ byte channelSpacing = OpenFlowValueMapper.lookupChannelSpacing(signal.channelSpacing());
+ mBuilder.setExact(MatchField.OCH_SIGID,
+ new CircuitSignalID(gridType, channelSpacing,
+ (short) signal.spacingMultiplier(), (short) signal.slotGranularity()));
+ } catch (NoMappingFoundException e) {
+ log.warn(e.getMessage());
+ }
+ break;
+ case OCH_SIGTYPE:
+ OchSignalTypeCriterion sc = (OchSignalTypeCriterion) c;
+ byte signalType = OpenFlowValueMapper.lookupOchSignalType(sc.signalType());
+ mBuilder.setExact(MatchField.OCH_SIGTYPE, U8.of(signalType));
+ break;
+ case TUNNEL_ID:
+ TunnelIdCriterion tunnelId = (TunnelIdCriterion) c;
+ mBuilder.setExact(MatchField.TUNNEL_ID,
+ U64.of(tunnelId.tunnelId()));
+ break;
+ case MPLS_BOS:
+ MplsBosCriterion mplsBos = (MplsBosCriterion) c;
+ mBuilder.setExact(MatchField.MPLS_BOS,
+ mplsBos.mplsBos() ? OFBooleanValue.TRUE
+ : OFBooleanValue.FALSE);
+ break;
+ case ARP_OP:
+ case ARP_SHA:
+ case ARP_SPA:
+ case ARP_THA:
+ case ARP_TPA:
+ case MPLS_TC:
+ case PBB_ISID:
+ default:
+ log.warn("Match type {} not yet implemented.", c.type());
+ }
+ }
+ return mBuilder.build();
+ }
+
+ /**
+ * Returns the flow rule for this builder.
+ *
+ * @return the flow rule
+ */
+ protected FlowRule flowRule() {
+ return flowRule;
+ }
+
+ /**
+ * Returns the factory used for building OpenFlow constructs.
+ *
+ * @return the factory
+ */
+ protected OFFactory factory() {
+ return factory;
+ }
+
+}
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java
new file mode 100644
index 00000000..c9de4500
--- /dev/null
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.of.flow.impl;
+
+import org.onlab.packet.Ip4Address;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFFlowAdd;
+import org.projectfloodlight.openflow.protocol.OFFlowDelete;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.match.Match;
+import org.projectfloodlight.openflow.types.IPv4Address;
+import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.types.OFBufferId;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.U64;
+import org.projectfloodlight.openflow.types.VlanPcp;
+import org.projectfloodlight.openflow.types.VlanVid;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Flow mod builder for OpenFlow 1.0.
+ */
+public class FlowModBuilderVer10 extends FlowModBuilder {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private static final int OFPCML_NO_BUFFER = 0xffff;
+
+ private final TrafficTreatment treatment;
+
+ /**
+ * Constructor for a flow mod builder for OpenFlow 1.0.
+ *
+ * @param flowRule the flow rule to transform into a flow mod
+ * @param factory the OpenFlow factory to use to build the flow mod
+ * @param xid the transaction ID
+ */
+ protected FlowModBuilderVer10(FlowRule flowRule,
+ OFFactory factory, Optional<Long> xid) {
+ super(flowRule, factory, xid);
+
+ this.treatment = flowRule.treatment();
+ }
+
+ @Override
+ public OFFlowAdd buildFlowAdd() {
+ Match match = buildMatch();
+ List<OFAction> actions = buildActions();
+
+ long cookie = flowRule().id().value();
+
+
+ OFFlowAdd fm = factory().buildFlowAdd()
+ .setXid(xid)
+ .setCookie(U64.of(cookie))
+ .setBufferId(OFBufferId.NO_BUFFER)
+ .setActions(actions)
+ .setMatch(match)
+ .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
+ .setPriority(flowRule().priority())
+ .build();
+
+ return fm;
+ }
+
+ @Override
+ public OFFlowMod buildFlowMod() {
+ Match match = buildMatch();
+ List<OFAction> actions = buildActions();
+
+ long cookie = flowRule().id().value();
+
+ OFFlowMod fm = factory().buildFlowModify()
+ .setXid(xid)
+ .setCookie(U64.of(cookie))
+ .setBufferId(OFBufferId.NO_BUFFER)
+ .setActions(actions)
+ .setMatch(match)
+ .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
+ .setPriority(flowRule().priority())
+ .build();
+
+ return fm;
+ }
+
+ @Override
+ public OFFlowDelete buildFlowDel() {
+ Match match = buildMatch();
+
+ long cookie = flowRule().id().value();
+
+ OFFlowDelete fm = factory().buildFlowDelete()
+ .setXid(xid)
+ .setCookie(U64.of(cookie))
+ .setBufferId(OFBufferId.NO_BUFFER)
+ .setMatch(match)
+ .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
+ .setPriority(flowRule().priority())
+ .build();
+
+ return fm;
+ }
+
+ private List<OFAction> buildActions() {
+ List<OFAction> acts = new LinkedList<>();
+ OFAction act;
+ if (treatment == null) {
+ return acts;
+ }
+ for (Instruction i : treatment.immediate()) {
+ switch (i.type()) {
+ case DROP:
+ log.warn("Saw drop action; assigning drop action");
+ return Collections.emptyList();
+ case L2MODIFICATION:
+ act = buildL2Modification(i);
+ if (act != null) {
+ acts.add(buildL2Modification(i));
+ }
+ break;
+ case L3MODIFICATION:
+ act = buildL3Modification(i);
+ if (act != null) {
+ acts.add(buildL3Modification(i));
+ }
+ break;
+ case OUTPUT:
+ OutputInstruction out = (OutputInstruction) i;
+ OFActionOutput.Builder action = factory().actions().buildOutput()
+ .setPort(OFPort.of((int) out.port().toLong()));
+ if (out.port().equals(PortNumber.CONTROLLER)) {
+ action.setMaxLen(OFPCML_NO_BUFFER);
+ }
+ acts.add(action.build());
+ break;
+ case L0MODIFICATION:
+ case GROUP:
+ case TABLE:
+ case METADATA:
+ log.warn("Instruction type {} not supported with protocol version {}",
+ i.type(), factory().getVersion());
+ break;
+ default:
+ log.warn("Instruction type {} not yet implemented.", i.type());
+ }
+ }
+
+ return acts;
+ }
+
+ private OFAction buildL3Modification(Instruction i) {
+ L3ModificationInstruction l3m = (L3ModificationInstruction) i;
+ ModIPInstruction ip;
+ Ip4Address ip4;
+ switch (l3m.subtype()) {
+ case IPV4_SRC:
+ ip = (ModIPInstruction) i;
+ ip4 = ip.ip().getIp4Address();
+ return factory().actions().setNwSrc(IPv4Address.of(ip4.toInt()));
+ case IPV4_DST:
+ ip = (ModIPInstruction) i;
+ ip4 = ip.ip().getIp4Address();
+ return factory().actions().setNwDst(IPv4Address.of(ip4.toInt()));
+ default:
+ log.warn("Unimplemented action type {}.", l3m.subtype());
+ break;
+ }
+ return null;
+ }
+
+ private OFAction buildL2Modification(Instruction i) {
+ L2ModificationInstruction l2m = (L2ModificationInstruction) i;
+ ModEtherInstruction eth;
+ switch (l2m.subtype()) {
+ case ETH_DST:
+ eth = (ModEtherInstruction) l2m;
+ return factory().actions().setDlDst(MacAddress.of(eth.mac().toLong()));
+ case ETH_SRC:
+ eth = (ModEtherInstruction) l2m;
+ return factory().actions().setDlSrc(MacAddress.of(eth.mac().toLong()));
+ case VLAN_ID:
+ ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
+ return factory().actions().setVlanVid(VlanVid.ofVlan(vlanId.vlanId().toShort()));
+ case VLAN_PCP:
+ ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
+ return factory().actions().setVlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
+ case VLAN_POP:
+ return factory().actions().stripVlan();
+ case VLAN_PUSH:
+ return null;
+ default:
+ log.warn("Unimplemented action type {}.", l2m.subtype());
+ break;
+ }
+ return null;
+ }
+
+}
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
new file mode 100644
index 00000000..8918d337
--- /dev/null
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
@@ -0,0 +1,458 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.of.flow.impl;
+
+import com.google.common.collect.Lists;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip6Address;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flow.instructions.Instructions.GroupInstruction;
+import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
+import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
+import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsBosInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
+import org.onosproject.net.flow.instructions.L4ModificationInstruction;
+import org.onosproject.net.flow.instructions.L4ModificationInstruction.ModTransportPortInstruction;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFFlowAdd;
+import org.projectfloodlight.openflow.protocol.OFFlowDelete;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
+import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
+import org.projectfloodlight.openflow.protocol.match.Match;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
+import org.projectfloodlight.openflow.types.CircuitSignalID;
+import org.projectfloodlight.openflow.types.EthType;
+import org.projectfloodlight.openflow.types.IPv4Address;
+import org.projectfloodlight.openflow.types.IPv6Address;
+import org.projectfloodlight.openflow.types.IPv6FlowLabel;
+import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.types.OFBooleanValue;
+import org.projectfloodlight.openflow.types.OFBufferId;
+import org.projectfloodlight.openflow.types.OFGroup;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.OFVlanVidMatch;
+import org.projectfloodlight.openflow.types.TableId;
+import org.projectfloodlight.openflow.types.TransportPort;
+import org.projectfloodlight.openflow.types.U32;
+import org.projectfloodlight.openflow.types.U64;
+import org.projectfloodlight.openflow.types.VlanPcp;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Flow mod builder for OpenFlow 1.3+.
+ */
+public class FlowModBuilderVer13 extends FlowModBuilder {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private static final int OFPCML_NO_BUFFER = 0xffff;
+
+ private final TrafficTreatment treatment;
+
+ /**
+ * Constructor for a flow mod builder for OpenFlow 1.3.
+ *
+ * @param flowRule the flow rule to transform into a flow mod
+ * @param factory the OpenFlow factory to use to build the flow mod
+ * @param xid the transaction ID
+ */
+ protected FlowModBuilderVer13(FlowRule flowRule, OFFactory factory, Optional<Long> xid) {
+ super(flowRule, factory, xid);
+
+ this.treatment = flowRule.treatment();
+ }
+
+ @Override
+ public OFFlowAdd buildFlowAdd() {
+ Match match = buildMatch();
+ List<OFAction> deferredActions = buildActions(treatment.deferred());
+ List<OFAction> immediateActions = buildActions(treatment.immediate());
+ List<OFInstruction> instructions = Lists.newLinkedList();
+
+
+ if (treatment.clearedDeferred()) {
+ instructions.add(factory().instructions().clearActions());
+ }
+ if (immediateActions.size() > 0) {
+ instructions.add(factory().instructions().applyActions(immediateActions));
+ }
+ if (deferredActions.size() > 0) {
+ instructions.add(factory().instructions().writeActions(deferredActions));
+ }
+ if (treatment.tableTransition() != null) {
+ instructions.add(buildTableGoto(treatment.tableTransition()));
+ }
+ if (treatment.writeMetadata() != null) {
+ instructions.add(buildMetadata(treatment.writeMetadata()));
+ }
+
+ long cookie = flowRule().id().value();
+
+ OFFlowAdd fm = factory().buildFlowAdd()
+ .setXid(xid)
+ .setCookie(U64.of(cookie))
+ .setBufferId(OFBufferId.NO_BUFFER)
+ .setInstructions(instructions)
+ .setMatch(match)
+ .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
+ .setPriority(flowRule().priority())
+ .setTableId(TableId.of(flowRule().tableId()))
+ .build();
+
+ return fm;
+ }
+
+ @Override
+ public OFFlowMod buildFlowMod() {
+ Match match = buildMatch();
+ List<OFAction> deferredActions = buildActions(treatment.deferred());
+ List<OFAction> immediateActions = buildActions(treatment.immediate());
+ List<OFInstruction> instructions = Lists.newLinkedList();
+
+
+ if (immediateActions.size() > 0) {
+ instructions.add(factory().instructions().applyActions(immediateActions));
+ }
+ if (treatment.clearedDeferred()) {
+ instructions.add(factory().instructions().clearActions());
+ }
+ if (deferredActions.size() > 0) {
+ instructions.add(factory().instructions().writeActions(deferredActions));
+ }
+ if (treatment.tableTransition() != null) {
+ instructions.add(buildTableGoto(treatment.tableTransition()));
+ }
+ if (treatment.writeMetadata() != null) {
+ instructions.add(buildMetadata(treatment.writeMetadata()));
+ }
+ if (treatment.metered() != null) {
+ instructions.add(buildMeter(treatment.metered()));
+ }
+
+ long cookie = flowRule().id().value();
+
+ OFFlowMod fm = factory().buildFlowModify()
+ .setXid(xid)
+ .setCookie(U64.of(cookie))
+ .setBufferId(OFBufferId.NO_BUFFER)
+ .setInstructions(instructions)
+ .setMatch(match)
+ .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
+ .setPriority(flowRule().priority())
+ .setTableId(TableId.of(flowRule().tableId()))
+ .build();
+
+ return fm;
+ }
+
+ @Override
+ public OFFlowDelete buildFlowDel() {
+ Match match = buildMatch();
+
+ long cookie = flowRule().id().value();
+
+ OFFlowDelete fm = factory().buildFlowDelete()
+ .setXid(xid)
+ .setCookie(U64.of(cookie))
+ .setBufferId(OFBufferId.NO_BUFFER)
+ .setMatch(match)
+ .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
+ .setPriority(flowRule().priority())
+ .setTableId(TableId.of(flowRule().tableId()))
+ .build();
+
+ return fm;
+ }
+
+ private List<OFAction> buildActions(List<Instruction> treatments) {
+ if (treatment == null) {
+ return Collections.emptyList();
+ }
+
+ boolean tableFound = false;
+ List<OFAction> actions = new LinkedList<>();
+ for (Instruction i : treatments) {
+ switch (i.type()) {
+ case DROP:
+ return Collections.emptyList();
+ case L0MODIFICATION:
+ actions.add(buildL0Modification(i));
+ break;
+ case L2MODIFICATION:
+ actions.add(buildL2Modification(i));
+ break;
+ case L3MODIFICATION:
+ actions.add(buildL3Modification(i));
+ break;
+ case L4MODIFICATION:
+ actions.add(buildL4Modification(i));
+ break;
+ case OUTPUT:
+ OutputInstruction out = (OutputInstruction) i;
+ OFActionOutput.Builder action = factory().actions().buildOutput()
+ .setPort(OFPort.of((int) out.port().toLong()));
+ if (out.port().equals(PortNumber.CONTROLLER)) {
+ action.setMaxLen(OFPCML_NO_BUFFER);
+ }
+ actions.add(action.build());
+ break;
+ case GROUP:
+ GroupInstruction group = (GroupInstruction) i;
+ OFActionGroup.Builder groupBuilder = factory().actions().buildGroup()
+ .setGroup(OFGroup.of(group.groupId().id()));
+ actions.add(groupBuilder.build());
+ break;
+ case TABLE:
+ //FIXME: should not occur here.
+ tableFound = true;
+ break;
+ default:
+ log.warn("Instruction type {} not yet implemented.", i.type());
+ }
+ }
+ if (tableFound && actions.isEmpty()) {
+ // handles the case where there are no actions, but there is
+ // a goto instruction for the next table
+ return Collections.emptyList();
+ }
+ return actions;
+ }
+
+ private OFInstruction buildTableGoto(Instructions.TableTypeTransition i) {
+ OFInstruction instruction = factory().instructions().gotoTable(
+ TableId.of(i.tableId()));
+ return instruction;
+ }
+
+ private OFInstruction buildMetadata(Instructions.MetadataInstruction m) {
+ OFInstruction instruction = factory().instructions().writeMetadata(
+ U64.of(m.metadata()), U64.of(m.metadataMask()));
+ return instruction;
+ }
+
+ private OFInstruction buildMeter(Instructions.MeterInstruction metered) {
+ return factory().instructions().meter(metered.meterId().id());
+ }
+
+
+ private OFAction buildL0Modification(Instruction i) {
+ L0ModificationInstruction l0m = (L0ModificationInstruction) i;
+ switch (l0m.subtype()) {
+ case LAMBDA:
+ return buildModLambdaInstruction((ModLambdaInstruction) i);
+ case OCH:
+ try {
+ return buildModOchSignalInstruction((ModOchSignalInstruction) i);
+ } catch (NoMappingFoundException e) {
+ log.warn(e.getMessage());
+ break;
+ }
+ default:
+ log.warn("Unimplemented action type {}.", l0m.subtype());
+ break;
+ }
+ return null;
+ }
+
+ private OFAction buildModLambdaInstruction(ModLambdaInstruction instruction) {
+ return factory().actions().circuit(factory().oxms().ochSigidBasic(
+ new CircuitSignalID((byte) 1, (byte) 2, instruction.lambda(), (short) 1)));
+ }
+
+ private OFAction buildModOchSignalInstruction(ModOchSignalInstruction instruction) {
+ OchSignal signal = instruction.lambda();
+ byte gridType = OpenFlowValueMapper.lookupGridType(signal.gridType());
+ byte channelSpacing = OpenFlowValueMapper.lookupChannelSpacing(signal.channelSpacing());
+
+ return factory().actions().circuit(factory().oxms().ochSigidBasic(
+ new CircuitSignalID(gridType, channelSpacing,
+ (short) signal.spacingMultiplier(), (short) signal.slotGranularity())
+ ));
+ }
+
+ private OFAction buildL2Modification(Instruction i) {
+ L2ModificationInstruction l2m = (L2ModificationInstruction) i;
+ ModEtherInstruction eth;
+ OFOxm<?> oxm = null;
+ switch (l2m.subtype()) {
+ case ETH_DST:
+ eth = (ModEtherInstruction) l2m;
+ oxm = factory().oxms().ethDst(MacAddress.of(eth.mac().toLong()));
+ break;
+ case ETH_SRC:
+ eth = (ModEtherInstruction) l2m;
+ oxm = factory().oxms().ethSrc(MacAddress.of(eth.mac().toLong()));
+ break;
+ case VLAN_ID:
+ ModVlanIdInstruction vlanId = (ModVlanIdInstruction) l2m;
+ oxm = factory().oxms().vlanVid(OFVlanVidMatch.ofVlan(vlanId.vlanId().toShort()));
+ break;
+ case VLAN_PCP:
+ ModVlanPcpInstruction vlanPcp = (ModVlanPcpInstruction) l2m;
+ oxm = factory().oxms().vlanPcp(VlanPcp.of(vlanPcp.vlanPcp()));
+ break;
+ case MPLS_PUSH:
+ PushHeaderInstructions pushHeaderInstructions =
+ (PushHeaderInstructions) l2m;
+ return factory().actions().pushMpls(EthType.of(pushHeaderInstructions
+ .ethernetType().toShort()));
+ case MPLS_POP:
+ PushHeaderInstructions popHeaderInstructions =
+ (PushHeaderInstructions) l2m;
+ return factory().actions().popMpls(EthType.of(popHeaderInstructions
+ .ethernetType().toShort()));
+ case MPLS_LABEL:
+ ModMplsLabelInstruction mplsLabel =
+ (ModMplsLabelInstruction) l2m;
+ oxm = factory().oxms().mplsLabel(U32.of(mplsLabel.mplsLabel().toInt()));
+ break;
+ case MPLS_BOS:
+ ModMplsBosInstruction mplsBos = (ModMplsBosInstruction) l2m;
+ oxm = factory().oxms()
+ .mplsBos(mplsBos.mplsBos() ? OFBooleanValue.TRUE
+ : OFBooleanValue.FALSE);
+ break;
+ case DEC_MPLS_TTL:
+ return factory().actions().decMplsTtl();
+ case VLAN_POP:
+ return factory().actions().popVlan();
+ case VLAN_PUSH:
+ PushHeaderInstructions pushVlanInstruction = (PushHeaderInstructions) l2m;
+ return factory().actions().pushVlan(
+ EthType.of(pushVlanInstruction.ethernetType().toShort()));
+ case TUNNEL_ID:
+ ModTunnelIdInstruction tunnelId = (ModTunnelIdInstruction) l2m;
+ oxm = factory().oxms().tunnelId(U64.of(tunnelId.tunnelId()));
+ break;
+ default:
+ log.warn("Unimplemented action type {}.", l2m.subtype());
+ break;
+ }
+
+ if (oxm != null) {
+ return factory().actions().buildSetField().setField(oxm).build();
+ }
+ return null;
+ }
+
+ private OFAction buildL3Modification(Instruction i) {
+ L3ModificationInstruction l3m = (L3ModificationInstruction) i;
+ ModIPInstruction ip;
+ Ip4Address ip4;
+ Ip6Address ip6;
+ OFOxm<?> oxm = null;
+ switch (l3m.subtype()) {
+ case IPV4_SRC:
+ ip = (ModIPInstruction) i;
+ ip4 = ip.ip().getIp4Address();
+ oxm = factory().oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
+ break;
+ case IPV4_DST:
+ ip = (ModIPInstruction) i;
+ ip4 = ip.ip().getIp4Address();
+ oxm = factory().oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
+ break;
+ case IPV6_SRC:
+ ip = (ModIPInstruction) i;
+ ip6 = ip.ip().getIp6Address();
+ oxm = factory().oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
+ break;
+ case IPV6_DST:
+ ip = (ModIPInstruction) i;
+ ip6 = ip.ip().getIp6Address();
+ oxm = factory().oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
+ break;
+ case IPV6_FLABEL:
+ ModIPv6FlowLabelInstruction flowLabelInstruction =
+ (ModIPv6FlowLabelInstruction) i;
+ int flowLabel = flowLabelInstruction.flowLabel();
+ oxm = factory().oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
+ break;
+ case DEC_TTL:
+ return factory().actions().decNwTtl();
+ case TTL_IN:
+ return factory().actions().copyTtlIn();
+ case TTL_OUT:
+ return factory().actions().copyTtlOut();
+ default:
+ log.warn("Unimplemented action type {}.", l3m.subtype());
+ break;
+ }
+
+ if (oxm != null) {
+ return factory().actions().buildSetField().setField(oxm).build();
+ }
+ return null;
+ }
+
+ private OFAction buildL4Modification(Instruction i) {
+ L4ModificationInstruction l4m = (L4ModificationInstruction) i;
+ ModTransportPortInstruction tp;
+ OFOxm<?> oxm = null;
+ switch (l4m.subtype()) {
+ case TCP_SRC:
+ tp = (ModTransportPortInstruction) l4m;
+ oxm = factory().oxms().tcpSrc(TransportPort.of(tp.port().toInt()));
+ break;
+ case TCP_DST:
+ tp = (ModTransportPortInstruction) l4m;
+ oxm = factory().oxms().tcpDst(TransportPort.of(tp.port().toInt()));
+ break;
+ case UDP_SRC:
+ tp = (ModTransportPortInstruction) l4m;
+ oxm = factory().oxms().udpSrc(TransportPort.of(tp.port().toInt()));
+ break;
+ case UDP_DST:
+ tp = (ModTransportPortInstruction) l4m;
+ oxm = factory().oxms().udpDst(TransportPort.of(tp.port().toInt()));
+ break;
+ default:
+ log.warn("Unimplemented action type {}.", l4m.subtype());
+ break;
+ }
+
+ if (oxm != null) {
+ return factory().actions().buildSetField().setField(oxm).build();
+ }
+ return null;
+ }
+
+}
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowStatsCollector.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowStatsCollector.java
new file mode 100644
index 00000000..c4c81afa
--- /dev/null
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowStatsCollector.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.of.flow.impl;
+
+import org.onlab.util.SharedExecutors;
+import org.onosproject.openflow.controller.OpenFlowSwitch;
+import org.onosproject.openflow.controller.RoleState;
+import org.projectfloodlight.openflow.protocol.OFFlowStatsRequest;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.TableId;
+import org.slf4j.Logger;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Collects flow statistics for the specified switch.
+ */
+class FlowStatsCollector {
+
+ private final Logger log = getLogger(getClass());
+
+ public static final int SECONDS = 1000;
+
+ private final OpenFlowSwitch sw;
+ private Timer timer;
+ private TimerTask task;
+
+ private int pollInterval;
+
+ /**
+ * Creates a new collector for the given switch and poll frequency.
+ *
+ * @param timer timer to use for scheduling
+ * @param sw switch to pull
+ * @param pollInterval poll frequency in seconds
+ */
+ FlowStatsCollector(Timer timer, OpenFlowSwitch sw, int pollInterval) {
+ this.timer = timer;
+ this.sw = sw;
+ this.pollInterval = pollInterval;
+ }
+
+ /**
+ * Adjusts poll frequency.
+ *
+ * @param pollInterval poll frequency in seconds
+ */
+ synchronized void adjustPollInterval(int pollInterval) {
+ this.pollInterval = pollInterval;
+ task.cancel();
+ task = new InternalTimerTask();
+ timer.scheduleAtFixedRate(task, pollInterval * SECONDS, pollInterval * 1000);
+ }
+
+ private class InternalTimerTask extends TimerTask {
+ @Override
+ public void run() {
+ if (sw.getRole() == RoleState.MASTER) {
+ log.trace("Collecting stats for {}", sw.getStringId());
+ OFFlowStatsRequest request = sw.factory().buildFlowStatsRequest()
+ .setMatch(sw.factory().matchWildcardAll())
+ .setTableId(TableId.ALL)
+ .setOutPort(OFPort.NO_MASK)
+ .build();
+ sw.sendMsg(request);
+ }
+ }
+ }
+
+ public synchronized void start() {
+ // Initially start polling quickly. Then drop down to configured value
+ log.debug("Starting Stats collection thread for {}", sw.getStringId());
+ task = new InternalTimerTask();
+ SharedExecutors.getTimer().scheduleAtFixedRate(task, 1 * SECONDS,
+ pollInterval * SECONDS);
+ }
+
+ public synchronized void stop() {
+ log.debug("Stopping Stats collection thread for {}", sw.getStringId());
+ task.cancel();
+ task = null;
+ }
+
+}
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NoMappingFoundException.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NoMappingFoundException.java
new file mode 100644
index 00000000..898b286d
--- /dev/null
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NoMappingFoundException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.of.flow.impl;
+
+/**
+ * Thrown to indicate that no mapping for the input value is found.
+ */
+public class NoMappingFoundException extends RuntimeException {
+ /**
+ * Creates an instance with the specified values.
+ *
+ * @param input input value of mapping causing this exception
+ * @param output the desired class which the input value is mapped to
+ */
+ public NoMappingFoundException(Object input, Class<?> output) {
+ super(String.format("No mapping found for %s when converting to %s", input, output.getName()));
+ }
+}
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
new file mode 100644
index 00000000..de079e03
--- /dev/null
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
@@ -0,0 +1,453 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.of.flow.impl;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.RemovalCause;
+import com.google.common.cache.RemovalNotification;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Modified;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.CompletedBatchOperation;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleBatchEntry;
+import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.FlowRuleExtPayLoad;
+import org.onosproject.net.flow.FlowRuleProvider;
+import org.onosproject.net.flow.FlowRuleProviderRegistry;
+import org.onosproject.net.flow.FlowRuleProviderService;
+import org.onosproject.net.provider.AbstractProvider;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.net.statistic.DefaultLoad;
+import org.onosproject.openflow.controller.Dpid;
+import org.onosproject.openflow.controller.OpenFlowController;
+import org.onosproject.openflow.controller.OpenFlowEventListener;
+import org.onosproject.openflow.controller.OpenFlowSwitch;
+import org.onosproject.openflow.controller.OpenFlowSwitchListener;
+import org.onosproject.openflow.controller.RoleState;
+import org.onosproject.openflow.controller.ThirdPartyMessage;
+import org.osgi.service.component.ComponentContext;
+import org.projectfloodlight.openflow.protocol.OFBadRequestCode;
+import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
+import org.projectfloodlight.openflow.protocol.OFErrorMsg;
+import org.projectfloodlight.openflow.protocol.OFErrorType;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
+import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortStatus;
+import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsType;
+import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg;
+import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg;
+import org.slf4j.Logger;
+
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.Timer;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static org.onlab.util.Tools.get;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Provider which uses an OpenFlow controller to detect network end-station
+ * hosts.
+ */
+@Component(immediate = true)
+public class OpenFlowRuleProvider extends AbstractProvider
+ implements FlowRuleProvider {
+
+ private final Logger log = getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowRuleProviderRegistry providerRegistry;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected OpenFlowController controller;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ComponentConfigService cfgService;
+
+ private static final int DEFAULT_POLL_FREQUENCY = 10;
+ @Property(name = "flowPollFrequency", intValue = DEFAULT_POLL_FREQUENCY,
+ label = "Frequency (in seconds) for polling flow statistics")
+ private int flowPollFrequency = DEFAULT_POLL_FREQUENCY;
+
+ private FlowRuleProviderService providerService;
+
+ private final InternalFlowProvider listener = new InternalFlowProvider();
+
+ private Cache<Long, InternalCacheEntry> pendingBatches;
+
+ private final Timer timer = new Timer("onos-openflow-collector");
+ private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap();
+
+ /**
+ * Creates an OpenFlow host provider.
+ */
+ public OpenFlowRuleProvider() {
+ super(new ProviderId("of", "org.onosproject.provider.openflow"));
+ }
+
+ @Activate
+ public void activate(ComponentContext context) {
+ cfgService.registerProperties(getClass());
+ providerService = providerRegistry.register(this);
+ controller.addListener(listener);
+ controller.addEventListener(listener);
+
+ pendingBatches = createBatchCache();
+ createCollectors();
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate(ComponentContext context) {
+ cfgService.unregisterProperties(getClass(), false);
+ stopCollectors();
+ providerRegistry.unregister(this);
+ providerService = null;
+
+ log.info("Stopped");
+ }
+
+ @Modified
+ public void modified(ComponentContext context) {
+ Dictionary<?, ?> properties = context.getProperties();
+ int newFlowPollFrequency;
+ try {
+ String s = get(properties, "flowPollFrequency");
+ newFlowPollFrequency = isNullOrEmpty(s) ? flowPollFrequency : Integer.parseInt(s.trim());
+
+ } catch (NumberFormatException | ClassCastException e) {
+ newFlowPollFrequency = flowPollFrequency;
+ }
+
+ if (newFlowPollFrequency != flowPollFrequency) {
+ flowPollFrequency = newFlowPollFrequency;
+ adjustRate();
+ }
+
+ log.info("Settings: flowPollFrequency={}", flowPollFrequency);
+ }
+
+ private Cache<Long, InternalCacheEntry> createBatchCache() {
+ return CacheBuilder.newBuilder()
+ .expireAfterWrite(10, TimeUnit.SECONDS)
+ .removalListener((RemovalNotification<Long, InternalCacheEntry> notification) -> {
+ if (notification.getCause() == RemovalCause.EXPIRED) {
+ providerService.batchOperationCompleted(notification.getKey(),
+ notification.getValue().failedCompletion());
+ }
+ }).build();
+ }
+
+ private void createCollectors() {
+ controller.getSwitches().forEach(this::createCollector);
+ }
+
+ private void createCollector(OpenFlowSwitch sw) {
+ FlowStatsCollector fsc = new FlowStatsCollector(timer, sw, flowPollFrequency);
+ fsc.start();
+ collectors.put(new Dpid(sw.getId()), fsc);
+ }
+
+ private void stopCollectors() {
+ collectors.values().forEach(FlowStatsCollector::stop);
+ collectors.clear();
+ }
+
+ private void adjustRate() {
+ DefaultLoad.setPollInterval(flowPollFrequency);
+ collectors.values().forEach(fsc -> fsc.adjustPollInterval(flowPollFrequency));
+ }
+
+ @Override
+ public void applyFlowRule(FlowRule... flowRules) {
+ for (FlowRule flowRule : flowRules) {
+ applyRule(flowRule);
+ }
+ }
+
+ private void applyRule(FlowRule flowRule) {
+ OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId()
+ .uri()));
+ FlowRuleExtPayLoad flowRuleExtPayLoad = flowRule.payLoad();
+ if (hasPayload(flowRuleExtPayLoad)) {
+ OFMessage msg = new ThirdPartyMessage(flowRuleExtPayLoad.payLoad());
+ sw.sendMsg(msg);
+ return;
+ }
+ sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
+ Optional.empty()).buildFlowAdd());
+ }
+
+ @Override
+ public void removeFlowRule(FlowRule... flowRules) {
+ for (FlowRule flowRule : flowRules) {
+ removeRule(flowRule);
+ }
+ }
+
+ private void removeRule(FlowRule flowRule) {
+ OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId()
+ .uri()));
+ FlowRuleExtPayLoad flowRuleExtPayLoad = flowRule.payLoad();
+ if (hasPayload(flowRuleExtPayLoad)) {
+ OFMessage msg = new ThirdPartyMessage(flowRuleExtPayLoad.payLoad());
+ sw.sendMsg(msg);
+ return;
+ }
+ sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
+ Optional.empty()).buildFlowDel());
+ }
+
+ @Override
+ public void removeRulesById(ApplicationId id, FlowRule... flowRules) {
+ // TODO: optimize using the ApplicationId
+ removeFlowRule(flowRules);
+ }
+
+ @Override
+ public void executeBatch(FlowRuleBatchOperation batch) {
+
+ pendingBatches.put(batch.id(), new InternalCacheEntry(batch));
+
+ OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(batch.deviceId()
+ .uri()));
+ OFFlowMod mod;
+ for (FlowRuleBatchEntry fbe : batch.getOperations()) {
+ // flow is the third party privacy flow
+
+ FlowRuleExtPayLoad flowRuleExtPayLoad = fbe.target().payLoad();
+ if (hasPayload(flowRuleExtPayLoad)) {
+ OFMessage msg = new ThirdPartyMessage(flowRuleExtPayLoad.payLoad());
+ sw.sendMsg(msg);
+ continue;
+ }
+ FlowModBuilder builder = FlowModBuilder.builder(fbe.target(), sw
+ .factory(), Optional.of(batch.id()));
+ switch (fbe.operator()) {
+ case ADD:
+ mod = builder.buildFlowAdd();
+ break;
+ case REMOVE:
+ mod = builder.buildFlowDel();
+ break;
+ case MODIFY:
+ mod = builder.buildFlowMod();
+ break;
+ default:
+ log.error("Unsupported batch operation {}; skipping flowmod {}",
+ fbe.operator(), fbe);
+ continue;
+ }
+ sw.sendMsg(mod);
+ }
+ OFBarrierRequest.Builder builder = sw.factory().buildBarrierRequest()
+ .setXid(batch.id());
+ sw.sendMsg(builder.build());
+ }
+
+ private boolean hasPayload(FlowRuleExtPayLoad flowRuleExtPayLoad) {
+ return flowRuleExtPayLoad != null &&
+ flowRuleExtPayLoad.payLoad() != null &&
+ flowRuleExtPayLoad.payLoad().length > 0;
+ }
+
+ private class InternalFlowProvider
+ implements OpenFlowSwitchListener, OpenFlowEventListener {
+
+ @Override
+ public void switchAdded(Dpid dpid) {
+ createCollector(controller.getSwitch(dpid));
+ }
+
+ @Override
+ public void switchRemoved(Dpid dpid) {
+ FlowStatsCollector collector = collectors.remove(dpid);
+ if (collector != null) {
+ collector.stop();
+ }
+ }
+
+ @Override
+ public void switchChanged(Dpid dpid) {
+ }
+
+ @Override
+ public void portChanged(Dpid dpid, OFPortStatus status) {
+ // TODO: Decide whether to evict flows internal store.
+ }
+
+ @Override
+ public void handleMessage(Dpid dpid, OFMessage msg) {
+ OpenFlowSwitch sw = controller.getSwitch(dpid);
+ switch (msg.getType()) {
+ case FLOW_REMOVED:
+ OFFlowRemoved removed = (OFFlowRemoved) msg;
+
+ FlowEntry fr = new FlowEntryBuilder(dpid, removed).build();
+ providerService.flowRemoved(fr);
+ break;
+ case STATS_REPLY:
+ if (((OFStatsReply) msg).getStatsType() == OFStatsType.FLOW) {
+ pushFlowMetrics(dpid, (OFFlowStatsReply) msg);
+ }
+ break;
+ case BARRIER_REPLY:
+ try {
+ InternalCacheEntry entry = pendingBatches.getIfPresent(msg.getXid());
+ if (entry != null) {
+ providerService
+ .batchOperationCompleted(msg.getXid(),
+ entry.completed());
+ } else {
+ log.warn("Received unknown Barrier Reply: {}",
+ msg.getXid());
+ }
+ } finally {
+ pendingBatches.invalidate(msg.getXid());
+ }
+ break;
+ case ERROR:
+ // TODO: This needs to get suppressed in a better way.
+ if (msg instanceof OFBadRequestErrorMsg &&
+ ((OFBadRequestErrorMsg) msg).getCode() == OFBadRequestCode.BAD_TYPE) {
+ log.debug("Received error message {} from {}", msg, dpid);
+ } else {
+ log.warn("Received error message {} from {}", msg, dpid);
+ }
+
+ OFErrorMsg error = (OFErrorMsg) msg;
+ if (error.getErrType() == OFErrorType.FLOW_MOD_FAILED) {
+ OFFlowModFailedErrorMsg fmFailed = (OFFlowModFailedErrorMsg) error;
+ if (fmFailed.getData().getParsedMessage().isPresent()) {
+ OFMessage m = fmFailed.getData().getParsedMessage().get();
+ OFFlowMod fm = (OFFlowMod) m;
+ InternalCacheEntry entry =
+ pendingBatches.getIfPresent(msg.getXid());
+ if (entry != null) {
+ entry.appendFailure(new FlowEntryBuilder(dpid, fm).build());
+ } else {
+ log.error("No matching batch for this error: {}", error);
+ }
+ } else {
+ // FIXME: Potentially add flowtracking to avoid this message.
+ log.error("Flow installation failed but switch didn't"
+ + " tell us which one.");
+ }
+ }
+ break;
+ default:
+ log.debug("Unhandled message type: {}", msg.getType());
+ }
+
+ }
+
+ @Override
+ public void receivedRoleReply(Dpid dpid, RoleState requested,
+ RoleState response) {
+ // Do nothing here for now.
+ }
+
+ private void pushFlowMetrics(Dpid dpid, OFFlowStatsReply replies) {
+
+ DeviceId did = DeviceId.deviceId(Dpid.uri(dpid));
+ OpenFlowSwitch sw = controller.getSwitch(dpid);
+
+ List<FlowEntry> flowEntries = replies.getEntries().stream()
+ .map(entry -> new FlowEntryBuilder(dpid, entry).build())
+ .collect(Collectors.toList());
+
+ providerService.pushFlowMetrics(did, flowEntries);
+ }
+ }
+
+ /**
+ * The internal cache entry holding the original request as well as
+ * accumulating the any failures along the way.
+ * <p/>
+ * If this entry is evicted from the cache then the entire operation is
+ * considered failed. Otherwise, only the failures reported by the device
+ * will be propagated up.
+ */
+ private class InternalCacheEntry {
+
+ private final FlowRuleBatchOperation operation;
+ private final Set<FlowRule> failures = Sets.newConcurrentHashSet();
+
+ public InternalCacheEntry(FlowRuleBatchOperation operation) {
+ this.operation = operation;
+ }
+
+ /**
+ * Appends a failed rule to the set of failed items.
+ *
+ * @param rule the failed rule
+ */
+ public void appendFailure(FlowRule rule) {
+ failures.add(rule);
+ }
+
+ /**
+ * Fails the entire batch and returns the failed operation.
+ *
+ * @return the failed operation
+ */
+ public CompletedBatchOperation failedCompletion() {
+ Set<FlowRule> fails = operation.getOperations().stream()
+ .map(op -> op.target()).collect(Collectors.toSet());
+ return new CompletedBatchOperation(false,
+ Collections
+ .unmodifiableSet(fails),
+ operation.deviceId());
+ }
+
+ /**
+ * Returns the completed operation and whether the batch suceeded.
+ *
+ * @return the completed operation
+ */
+ public CompletedBatchOperation completed() {
+ return new CompletedBatchOperation(
+ failures.isEmpty(),
+ Collections
+ .unmodifiableSet(failures),
+ operation.deviceId());
+ }
+ }
+
+}
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowValueMapper.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowValueMapper.java
new file mode 100644
index 00000000..2f0831c6
--- /dev/null
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowValueMapper.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.of.flow.impl;
+
+import com.google.common.collect.BiMap;
+import com.google.common.collect.EnumHashBiMap;
+import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.GridType;
+import org.onosproject.net.OchSignalType;
+
+/**
+ * Collection of helper methods to convert protocol agnostic models to values used in OpenFlow spec.
+ */
+final class OpenFlowValueMapper {
+
+ // prohibit instantiation
+ private OpenFlowValueMapper() {}
+
+ private static final BiMap<GridType, Byte> GRID_TYPES = EnumHashBiMap.create(GridType.class);
+ static {
+ // See ONF "Optical Transport Protocol Extensions Version 1.0" for the following values
+ GRID_TYPES.put(GridType.DWDM, (byte) 1); // OFPGRIDT_DWDM of enum ofp_grid_type
+ GRID_TYPES.put(GridType.CWDM, (byte) 2); // OFPGRIDT_CWDM of enum ofp_grid_type
+ GRID_TYPES.put(GridType.FLEX, (byte) 3); // OFPGRIDT_FLEX of enum ofp_grid_type
+ }
+
+ private static final BiMap<ChannelSpacing, Byte> CHANNEL_SPACING = EnumHashBiMap.create(ChannelSpacing.class);
+ static {
+ // See ONF "Optical Transport Protocol Extensions Version 1.0" for the following values
+ CHANNEL_SPACING.put(ChannelSpacing.CHL_100GHZ, (byte) 1); // OFPCS_100GHZ of enum ofp_chl_spacing
+ CHANNEL_SPACING.put(ChannelSpacing.CHL_50GHZ, (byte) 2); // OFPCS_50GHZ of enum ofp_chl_spacing
+ CHANNEL_SPACING.put(ChannelSpacing.CHL_25GHZ, (byte) 3); // OFPCS_25GHZ of enum ofp_chl_spacing
+ CHANNEL_SPACING.put(ChannelSpacing.CHL_12P5GHZ, (byte) 4); // OFPCS_12P5GHZ of enum ofp_chl_spacing
+ CHANNEL_SPACING.put(ChannelSpacing.CHL_6P25GHZ, (byte) 5); // OFPCS_6P25GHZ of enum ofp_chl_spacing
+ }
+
+ private static final BiMap<OchSignalType, Byte> OCH_SIGNAL_TYPES = EnumHashBiMap.create(OchSignalType.class);
+ static {
+ // See ONF "Optical Transport Protocol Extensions Version 1.0" for the following values
+ OCH_SIGNAL_TYPES.put(OchSignalType.FIXED_GRID, (byte) 1); // OFPOCHT_FIX_GRID of enum ofp_och_signal_type
+ OCH_SIGNAL_TYPES.put(OchSignalType.FLEX_GRID, (byte) 2); // OFPOCHT_FLEX_GRID of enum ofp_och_signal_type
+ }
+
+ /**
+ * Looks up the specified input value to the corresponding value with the specified map.
+ *
+ * @param map bidirectional mapping
+ * @param input input value
+ * @param cls class of output value
+ * @param <I> type of input value
+ * @param <O> type of output value
+ * @return the corresponding value stored in the specified map
+ * @throws NoMappingFoundException if no corresponding value is found
+ */
+ private static <I, O> O lookup(BiMap<I, O> map, I input, Class<O> cls) {
+ if (!map.containsKey(input)) {
+ throw new NoMappingFoundException(input, cls);
+ }
+
+ return map.get(input);
+ }
+
+ /**
+ * Looks up the corresponding byte value defined in
+ * ONF "Optical Transport Protocol Extensions Version 1.0"
+ * from the specified {@link GridType} instance.
+ *
+ * @param type grid type
+ * @return the byte value corresponding to the specified grid type
+ * @throws NoMappingFoundException if the specified grid type is not found
+ */
+ static byte lookupGridType(GridType type) {
+ return lookup(GRID_TYPES, type, Byte.class);
+ }
+
+ /**
+ * Looks up the corresponding {@link GridType} instance
+ * from the specified byte value for grid type
+ * defined in ONF "Optical Transport Protocol Extensions Version 1.0".
+ *
+ * @param type byte value as grid type defined the spec
+ * @return the corresponding GridType instance
+ */
+ static GridType lookupGridType(byte type) {
+ return lookup(GRID_TYPES.inverse(), type, GridType.class);
+ }
+
+ /**
+ * Looks up the corresponding byte value for channel spacing defined in
+ * ONF "Optical Transport Protocol Extensions Version 1.0"
+ * from the specified {@link ChannelSpacing} instance.
+ *
+ * @param spacing channel spacing
+ * @return byte value corresponding to the specified channel spacing
+ * @throws NoMappingFoundException if the specified channel spacing is not found
+ */
+ static byte lookupChannelSpacing(ChannelSpacing spacing) {
+ return lookup(CHANNEL_SPACING, spacing, Byte.class);
+ }
+
+ /**
+ * Looks up the corresponding {@link ChannelSpacing} instance
+ * from the specified byte value for channel spacing
+ * defined in ONF "Optical Transport Protocol Extensions Version 1.0".
+ *
+ * @param spacing byte value as channel spacing defined the spec
+ * @return the corresponding ChannelSpacing instance
+ * @throws NoMappingFoundException if the specified channel spacing is not found
+ */
+ static ChannelSpacing lookupChannelSpacing(byte spacing) {
+ return lookup(CHANNEL_SPACING.inverse(), spacing, ChannelSpacing.class);
+ }
+
+ /**
+ * Looks up the corresponding byte value for Och signal type defined in
+ * ONF "Optical Transport Protocol Extensions Version 1.0"
+ * from the specified {@link OchSignalType} instance.
+ *
+ * @param signalType optical signal type
+ * @return byte value corresponding to the specified OCh signal type
+ * @throws NoMappingFoundException if the specified Och signal type is not found
+ */
+ static byte lookupOchSignalType(OchSignalType signalType) {
+ return lookup(OCH_SIGNAL_TYPES, signalType, Byte.class);
+ }
+
+ /**
+ * Looks up the the corresponding {@link OchSignalType} instance
+ * from the specified byte value for Och signal type defined in
+ * ONF "Optical Transport Protocol Extensions Version 1.0".
+ *
+ * @param signalType byte value as Och singal type defined the spec
+ * @return the corresponding OchSignalType instance
+ * @throws NoMappingFoundException if the specified Och signal type is not found
+ */
+ static OchSignalType lookupOchSignalType(byte signalType) {
+ return lookup(OCH_SIGNAL_TYPES.inverse(), signalType, OchSignalType.class);
+ }
+}
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/package-info.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/package-info.java
new file mode 100644
index 00000000..2acc1510
--- /dev/null
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Provider that uses OpenFlow controller as a means of ending and receiving flow information.
+ */
+package org.onosproject.provider.of.flow.impl;