blob: 14d8b928fabe8eacc125fac8f33a94d10e0dd7a7 [file] [log] [blame]
package net.onrc.onos.core.intent;
import java.util.Objects;
import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.core.packet.Ethernet;
import net.onrc.onos.core.util.FlowEntryMatch;
import net.onrc.onos.core.util.IPv4;
import net.onrc.onos.core.util.IPv4Net;
import net.onrc.onos.core.util.PortNumber;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.match.Match.Builder;
import org.projectfloodlight.openflow.protocol.match.MatchField;
import org.projectfloodlight.openflow.types.EthType;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.OFPort;
/**
* A class to represent the OpenFlow match.
* <p>
* At the moment, the supported match conditions are:
* <ul>
* <li>source port
* <li>source and destination MAC address
* <li>source and destination IP address
* </ul>
* <p>
* TODO: extend this object to allow more match conditions
*/
public class Match {
private static final short IPV4_PREFIX_LEN = 32;
protected long sw;
protected MACAddress srcMac;
protected MACAddress dstMac;
protected int srcIp;
protected int dstIp;
protected long srcPort;
/**
* Constructor for Ethernet-based matches.
*
* @param sw switch's DPID
* @param srcPort source port on switch
* @param srcMac source Ethernet MAC address
* @param dstMac destination Ethernet MAC address
*/
public Match(long sw, long srcPort,
MACAddress srcMac, MACAddress dstMac) {
this(sw, srcPort, srcMac, dstMac,
ShortestPathIntent.EMPTYIPADDRESS,
ShortestPathIntent.EMPTYIPADDRESS);
}
/**
* Generic constructor.
*
* @param sw switch's DPID
* @param srcPort source port on switch
* @param srcMac source Ethernet MAC address
* @param dstMac destination Ethernet MAC address
* @param srcIp source IP address
* @param dstIp destination IP address
*/
public Match(long sw, long srcPort, MACAddress srcMac, MACAddress dstMac,
int srcIp, int dstIp) {
this.sw = sw;
this.srcPort = srcPort;
this.srcMac = srcMac;
this.dstMac = dstMac;
this.srcIp = srcIp;
this.dstIp = dstIp;
}
/**
* Matches are equal if all object variables are equal.
*
* @return true if equal, false otherwise
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof Match) {
Match other = (Match) obj;
// TODO: we might consider excluding sw from this comparison
if (this.sw != other.sw) {
return false;
}
if (!Objects.equals(srcMac, other.srcMac)) {
return false;
}
if (!Objects.equals(dstMac, other.dstMac)) {
return false;
}
if (srcIp != other.srcIp) {
return false;
}
if (dstIp != other.dstIp) {
return false;
}
if (this.srcPort != other.srcPort) {
return false;
}
return true;
} else {
return false;
}
}
/**
* Converts the Match into a legacy FlowEntryMatch object.
*
* @return an equivalent FlowEntryMatch object
*/
public FlowEntryMatch getFlowEntryMatch() {
FlowEntryMatch match = new FlowEntryMatch();
if (srcMac != null) {
match.enableSrcMac(srcMac);
}
if (dstMac != null) {
match.enableDstMac(dstMac);
}
if (srcIp != ShortestPathIntent.EMPTYIPADDRESS) {
match.enableEthernetFrameType(Ethernet.TYPE_IPV4);
IPv4 srcIPv4 = new IPv4(srcIp);
IPv4Net srcIP = new IPv4Net(srcIPv4, IPV4_PREFIX_LEN);
match.enableSrcIPv4Net(srcIP);
}
if (dstIp != ShortestPathIntent.EMPTYIPADDRESS) {
match.enableEthernetFrameType(Ethernet.TYPE_IPV4);
IPv4 dstIPv4 = new IPv4(dstIp);
IPv4Net dstIP = new IPv4Net(dstIPv4, IPV4_PREFIX_LEN);
match.enableDstIPv4Net(dstIP);
}
match.enableInPort(new PortNumber((short) srcPort));
return match;
}
public Builder getOFMatchBuilder(OFFactory factory) {
Builder matchBuilder = factory.buildMatch();
if (srcMac != null) {
matchBuilder.setExact(MatchField.ETH_SRC, MacAddress.of(srcMac.toLong()));
}
if (dstMac != null) {
matchBuilder.setExact(MatchField.ETH_DST, MacAddress.of(dstMac.toLong()));
}
if (srcIp != ShortestPathIntent.EMPTYIPADDRESS) {
matchBuilder.setExact(MatchField.ETH_TYPE, EthType.IPv4)
.setMasked(MatchField.IPV4_SRC,
IPv4Address.of(srcIp).withMaskOfLength(IPV4_PREFIX_LEN));
}
if (dstIp != ShortestPathIntent.EMPTYIPADDRESS) {
matchBuilder.setExact(MatchField.ETH_TYPE, EthType.IPv4)
.setMasked(MatchField.IPV4_DST,
IPv4Address.of(dstIp).withMaskOfLength(IPV4_PREFIX_LEN));
}
matchBuilder.setExact(MatchField.IN_PORT, OFPort.of((int) srcPort));
return matchBuilder;
}
/**
* Returns a String representation of this Match.
*
* @return the match as a String
*/
@Override
public String toString() {
return "Sw:" + sw + " (" + srcPort + ","
+ srcMac + "," + dstMac + ","
+ srcIp + "," + dstIp + ")";
}
/**
* Generates hash using Objects.hash() to hash all object variables.
*
* @return hashcode
*/
@Override
public int hashCode() {
// TODO: we might consider excluding sw from the hash function
// to make it easier to compare matches between switches
return Objects.hash(sw, srcPort, srcMac, dstMac, srcIp, dstIp);
}
}