Charles M.C. Chan
Committed by Pavlin Radoslavov

ONOS-509: Match IPV6_SRC, IPV6_DST criteria

* Following classes have been extended to match IPV6_SRC and IPV6_DST criteria:
    - Criteria
    - DefaultTrafficSelector
    - FlowEntryBuilder
    - FlowModBuilder

* Not included in this submission
    - Match of other IPv6-related criteria
    - Set of all IPv6-related criteria (action)

Change-Id: I115829a480356d2037e0fc809595f7a5eec25874
......@@ -184,6 +184,16 @@ public final class DefaultTrafficSelector implements TrafficSelector {
}
@Override
public Builder matchIPv6Src(IpPrefix ip) {
return add(Criteria.matchIPv6Src(ip));
}
@Override
public Builder matchIPv6Dst(IpPrefix ip) {
return add(Criteria.matchIPv6Dst(ip));
}
@Override
public Builder matchMplsLabel(Integer mplsLabel) {
return add(Criteria.matchMplsLabel(mplsLabel));
}
......
......@@ -115,7 +115,7 @@ public interface TrafficSelector {
public Builder matchIPProtocol(Byte proto);
/**
* Matches a l3 address.
* Matches a l3 IPv4 address.
*
* @param ip a l3 address
* @return a selection builder
......@@ -123,7 +123,7 @@ public interface TrafficSelector {
public Builder matchIPSrc(IpPrefix ip);
/**
* Matches a l3 address.
* Matches a l3 IPv4 address.
*
* @param ip a l3 address
* @return a selection builder
......@@ -146,6 +146,21 @@ public interface TrafficSelector {
*/
public Builder matchTcpDst(Short tcpPort);
/**
* Matches a l3 IPv6 address.
*
* @param ip a l3 IPv6 address
* @return a selection builder
*/
public Builder matchIPv6Src(IpPrefix ip);
/**
* Matches a l3 IPv6 address.
*
* @param ip a l3 IPv6 address
* @return a selection builder
*/
public Builder matchIPv6Dst(IpPrefix ip);
/**
* Matches on a MPLS label .
......
......@@ -18,7 +18,6 @@ package org.onosproject.net.flow.criteria;
import static com.google.common.base.MoreObjects.toStringHelper;
import java.util.Objects;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.criteria.Criterion.Type;
import org.onlab.packet.IpPrefix;
......@@ -109,9 +108,9 @@ public final class Criteria {
}
/**
* Creates a match on IP source field using the specified value.
* Creates a match on IPv4 source field using the specified value.
*
* @param ip ip source value
* @param ip ipv4 source value
* @return match criterion
*/
public static Criterion matchIPSrc(IpPrefix ip) {
......@@ -119,9 +118,9 @@ public final class Criteria {
}
/**
* Creates a match on IP destination field using the specified value.
* Creates a match on IPv4 destination field using the specified value.
*
* @param ip ip source value
* @param ip ipv4 source value
* @return match criterion
*/
public static Criterion matchIPDst(IpPrefix ip) {
......@@ -149,6 +148,26 @@ public final class Criteria {
}
/**
* Creates a match on IPv6 source field using the specified value.
*
* @param ip ipv6 source value
* @return match criterion
*/
public static Criterion matchIPv6Src(IpPrefix ip) {
return new IPCriterion(ip, Type.IPV6_SRC);
}
/**
* Creates a match on IPv6 destination field using the specified value.
*
* @param ip ipv6 source value
* @return match criterion
*/
public static Criterion matchIPv6Dst(IpPrefix ip) {
return new IPCriterion(ip, Type.IPV6_DST);
}
/**
* Creates a match on MPLS label.
* @param mplsLabel MPLS label
* @return match criterion
......
......@@ -129,6 +129,7 @@ public class DefaultTrafficSelectorTest {
final short shortValue = 33;
final byte byteValue = 44;
final IpPrefix ipPrefixValue = IpPrefix.valueOf("192.168.1.0/24");
final IpPrefix ipv6PrefixValue = IpPrefix.valueOf("fe80::1/64");
selector = DefaultTrafficSelector.builder()
.matchInport(PortNumber.portNumber(11)).build();
......@@ -175,6 +176,14 @@ public class DefaultTrafficSelectorTest {
assertThat(selector, hasCriterionWithType(Type.TCP_DST));
selector = DefaultTrafficSelector.builder()
.matchIPv6Src(ipv6PrefixValue).build();
assertThat(selector, hasCriterionWithType(Type.IPV6_SRC));
selector = DefaultTrafficSelector.builder()
.matchIPv6Dst(ipv6PrefixValue).build();
assertThat(selector, hasCriterionWithType(Type.IPV6_DST));
selector = DefaultTrafficSelector.builder()
.matchMplsLabel(3).build();
assertThat(selector, hasCriterionWithType(Type.MPLS_LABEL));
......
......@@ -84,11 +84,18 @@ public class CriteriaTest {
private static final String IP1 = "1.2.3.4/24";
private static final String IP2 = "5.6.7.8/24";
private static final String IPV61 = "fe80::1/64";
private static final String IPV62 = "fc80::2/64";
private IpPrefix ip1 = IpPrefix.valueOf(IP1);
private IpPrefix ip2 = IpPrefix.valueOf(IP2);
private IpPrefix ipv61 = IpPrefix.valueOf(IPV61);
private IpPrefix ipv62 = IpPrefix.valueOf(IPV62);
Criterion matchIp1 = Criteria.matchIPSrc(ip1);
Criterion sameAsMatchIp1 = Criteria.matchIPSrc(ip1);
Criterion matchIp2 = Criteria.matchIPSrc(ip2);
Criterion matchIpv61 = Criteria.matchIPSrc(ipv61);
Criterion sameAsMatchIpv61 = Criteria.matchIPSrc(ipv61);
Criterion matchIpv62 = Criteria.matchIPSrc(ipv62);
short lambda1 = 1;
short lambda2 = 2;
......@@ -384,6 +391,32 @@ public class CriteriaTest {
}
/**
* Test the matchIPSrc method.
*/
@Test
public void testMatchIPv6SrcMethod() {
Criterion matchIpv6Src = Criteria.matchIPv6Src(ipv61);
Criteria.IPCriterion ipCriterion =
checkAndConvert(matchIpv6Src,
Criterion.Type.IPV6_SRC,
Criteria.IPCriterion.class);
assertThat(ipCriterion.ip(), is(ipv61));
}
/**
* Test the matchIPDst method.
*/
@Test
public void testMatchIPv6DstMethod() {
Criterion matchIPv6Dst = Criteria.matchIPv6Dst(ipv61);
Criteria.IPCriterion ipCriterion =
checkAndConvert(matchIPv6Dst,
Criterion.Type.IPV6_DST,
Criteria.IPCriterion.class);
assertThat(ipCriterion.ip(), is(equalTo(ipv61)));
}
/**
* Test the equals() method of the IpCriterion class.
*/
@Test
......@@ -392,6 +425,11 @@ public class CriteriaTest {
.addEqualityGroup(matchIp1, sameAsMatchIp1)
.addEqualityGroup(matchIp2)
.testEquals();
new EqualsTester()
.addEqualityGroup(matchIpv61, sameAsMatchIpv61)
.addEqualityGroup(matchIpv62)
.testEquals();
}
// LambdaCriterion class
......
......@@ -21,6 +21,7 @@ import java.util.List;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.Ip6Prefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.net.DeviceId;
......@@ -56,6 +57,7 @@ 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.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.VlanPcp;
......@@ -398,6 +400,34 @@ public class FlowEntryBuilder {
builder.matchOpticalSignalType(match.get(MatchField
.OCH_SIGTYPE).getValue());
break;
case IPV6_DST:
Ip6Prefix dipv6;
if (match.isPartiallyMasked(MatchField.IPV6_DST)) {
Masked<IPv6Address> maskedIp = match.getMasked(MatchField.IPV6_DST);
dipv6 = Ip6Prefix.valueOf(
maskedIp.getValue().getBytes(),
maskedIp.getMask().asCidrMaskLength());
} else {
dipv6 = Ip6Prefix.valueOf(
match.get(MatchField.IPV6_DST).getBytes(),
Ip6Prefix.MAX_MASK_LENGTH);
}
builder.matchIPv6Dst(dipv6);
break;
case IPV6_SRC:
Ip6Prefix sipv6;
if (match.isPartiallyMasked(MatchField.IPV6_SRC)) {
Masked<IPv6Address> maskedIp = match.getMasked(MatchField.IPV6_SRC);
sipv6 = Ip6Prefix.valueOf(
maskedIp.getValue().getBytes(),
maskedIp.getMask().asCidrMaskLength());
} else {
sipv6 = Ip6Prefix.valueOf(
match.get(MatchField.IPV6_SRC).getBytes(),
Ip6Prefix.MAX_MASK_LENGTH);
}
builder.matchIPv6Src(sipv6);
break;
case ARP_OP:
case ARP_SHA:
case ARP_SPA:
......@@ -408,12 +438,10 @@ public class FlowEntryBuilder {
case ICMPV6_CODE:
case ICMPV6_TYPE:
case IN_PHY_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 METADATA:
......@@ -425,8 +453,6 @@ public class FlowEntryBuilder {
case UDP_SRC:
default:
log.warn("Match type {} not yet implemented.", field.id);
}
}
return builder.build();
......
......@@ -17,6 +17,8 @@ package org.onosproject.provider.of.flow.impl;
import static org.slf4j.LoggerFactory.getLogger;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.Ip6Prefix;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.criteria.Criteria;
......@@ -41,6 +43,7 @@ import org.projectfloodlight.openflow.protocol.match.MatchField;
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.IpProtocol;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.Masked;
......@@ -134,6 +137,7 @@ public abstract class FlowModBuilder {
EthCriterion eth;
IPCriterion ip;
Ip4Prefix ip4Prefix;
Ip6Prefix ip6Prefix;
TcpPortCriterion tp;
for (Criterion c : selector.criteria()) {
switch (c.type()) {
......@@ -220,6 +224,36 @@ public abstract class FlowModBuilder {
mBuilder.setExact(MatchField.OCH_SIGTYPE,
U8.of(sc.signalType()));
break;
case IPV6_DST:
ip = (IPCriterion) c;
ip6Prefix = ip.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_SRC:
ip = (IPCriterion) c;
ip6Prefix = ip.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 ARP_OP:
case ARP_SHA:
case ARP_SPA:
......@@ -230,13 +264,11 @@ public abstract class FlowModBuilder {
case ICMPV6_CODE:
case ICMPV6_TYPE:
case IN_PHY_PORT:
case IPV6_DST:
case IPV6_EXTHDR:
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 METADATA:
......