diff options
Diffstat (limited to 'framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java')
-rw-r--r-- | framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java | 444 |
1 files changed, 444 insertions, 0 deletions
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; + } + +} |