Pavlin Radoslavov

Implement some of the missing Selector and Match Conditions

Work toward ONOS-509

The following match conditions are added/implemented:
  - IPV6_EXTHDR

Also, fixed the match criteria for the optical signal type
to represent unsigned 8 bits integer (per spec).

Change-Id: I925db19cb43c5d9f589c1f090b6a75faabe0a19b
......@@ -280,6 +280,11 @@ public final class DefaultTrafficSelector implements TrafficSelector {
}
@Override
public Builder matchIPv6ExthdrFlags(Integer exthdrFlags) {
return add(Criteria.matchIPv6ExthdrFlags(exthdrFlags));
}
@Override
public Builder matchLambda(Short lambda) {
return add(Criteria.matchLambda(lambda));
}
......
......@@ -300,6 +300,14 @@ public interface TrafficSelector {
public Builder matchMplsLabel(Integer mplsLabel);
/**
* Matches on IPv6 Extension Header pseudo-field fiags.
*
* @param exthdrFlags the IPv6 Extension Header pseudo-field fiags
* @return a selection builder
*/
public Builder matchIPv6ExthdrFlags(Integer exthdrFlags);
/**
* Matches an optical signal ID or lambda.
*
* @param lambda lamda
......
......@@ -62,7 +62,7 @@ public final class Criteria {
* @param metadata metadata value (64 bits data)
* @return match criterion
*/
public static Criterion matchMetadata(Long metadata) {
public static Criterion matchMetadata(long metadata) {
return new MetadataCriterion(metadata);
}
......@@ -338,11 +338,22 @@ public final class Criteria {
* @param mplsLabel MPLS label (20 bits)
* @return match criterion
*/
public static Criterion matchMplsLabel(Integer mplsLabel) {
public static Criterion matchMplsLabel(int mplsLabel) {
return new MplsCriterion(mplsLabel);
}
/**
* Creates a match on IPv6 Extension Header pseudo-field fiags.
* Those are defined in Criterion.IPv6ExthdrFlags.
*
* @param exthdrFlags IPv6 Extension Header pseudo-field flags (16 bits)
* @return match criterion
*/
public static Criterion matchIPv6ExthdrFlags(int exthdrFlags) {
return new IPv6ExthdrFlagsCriterion(exthdrFlags);
}
/**
* Creates a match on lambda field using the specified value.
*
* @param lambda lambda to match on (16 bits unsigned integer)
......@@ -355,10 +366,10 @@ public final class Criteria {
/**
* Creates a match on optical signal type using the specified value.
*
* @param sigType optical signal type (16 bits unsigned integer)
* @param sigType optical signal type (8 bits unsigned integer)
* @return match criterion
*/
public static Criterion matchOpticalSignalType(int sigType) {
public static Criterion matchOpticalSignalType(short sigType) {
return new OpticalSignalTypeCriterion(sigType, Type.OCH_SIGTYPE);
}
......@@ -1550,6 +1561,64 @@ public final class Criteria {
}
/**
* Implementation of IPv6 Extension Header pseudo-field criterion
* (16 bits). Those are defined in Criterion.IPv6ExthdrFlags.
*/
public static final class IPv6ExthdrFlagsCriterion implements Criterion {
private static final int MASK = 0xffff;
private final int exthdrFlags; // IPv6 Exthdr flags: 16 bits
/**
* Constructor.
*
* @param exthdrFlags the IPv6 Extension Header pseudo-field flags
* to match (16 bits). Those are defined in Criterion.IPv6ExthdrFlags
*/
public IPv6ExthdrFlagsCriterion(int exthdrFlags) {
this.exthdrFlags = exthdrFlags & MASK;
}
@Override
public Type type() {
return Type.IPV6_EXTHDR;
}
/**
* Gets the IPv6 Extension Header pseudo-field flags to match.
*
* @return the IPv6 Extension Header pseudo-field flags to match
* (16 bits). Those are defined in Criterion.IPv6ExthdrFlags
*/
public int exthdrFlags() {
return exthdrFlags;
}
@Override
public String toString() {
return toStringHelper(type().toString())
.add("exthdrFlags", Long.toHexString(exthdrFlags)).toString();
}
@Override
public int hashCode() {
return Objects.hash(type(), exthdrFlags);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof IPv6ExthdrFlagsCriterion) {
IPv6ExthdrFlagsCriterion that = (IPv6ExthdrFlagsCriterion) obj;
return Objects.equals(exthdrFlags, that.exthdrFlags) &&
Objects.equals(this.type(), that.type());
}
return false;
}
}
/**
* Implementation of lambda (wavelength) criterion (16 bits unsigned
* integer).
*/
......@@ -1610,23 +1679,23 @@ public final class Criteria {
}
/**
* Implementation of optical signal type criterion (16 bits unsigned
* Implementation of optical signal type criterion (8 bits unsigned
* integer).
*/
public static final class OpticalSignalTypeCriterion implements Criterion {
private static final int MASK = 0xffff;
private final int signalType; // Signal type value: 16 bits
private static final short MASK = 0xff;
private final short signalType; // Signal type value: 8 bits
private final Type type;
/**
* Constructor.
*
* @param signalType the optical signal type to match (16 bits unsigned
* @param signalType the optical signal type to match (8 bits unsigned
* integer)
* @param type the match type. Should be Type.OCH_SIGTYPE
*/
public OpticalSignalTypeCriterion(int signalType, Type type) {
this.signalType = signalType & MASK;
public OpticalSignalTypeCriterion(short signalType, Type type) {
this.signalType = (short) (signalType & MASK);
this.type = type;
}
......@@ -1638,9 +1707,9 @@ public final class Criteria {
/**
* Gets the optical signal type to match.
*
* @return the optical signal type to match
* @return the optical signal type to match (8 bits unsigned integer)
*/
public int signalType() {
public short signalType() {
return signalType;
}
......
......@@ -129,11 +129,48 @@ public interface Criterion {
/**
* Returns the type of criterion.
*
* @return type of criterion
*/
public Type type();
// TODO: Create factory class 'Criteria' that will have various factory
// to create specific criterions.
/**
* Bit definitions for IPv6 Extension Header pseudo-field.
* From page 79 of OpenFlow 1.5.0 spec.
*/
public enum IPv6ExthdrFlags {
/** "No next header" encountered. */
NONEXT(1 << 0),
/** Encrypted Sec Payload header present. */
ESP(1 << 1),
/** Authentication header present. */
AUTH(1 << 2),
/** 1 or 2 dest headers present. */
DEST(1 << 3),
/** Fragment header present. */
FRAG(1 << 4),
/** Router header present. */
ROUTER(1 << 5),
/** Hop-by-hop header present. */
HOP(1 << 6),
/** Unexpected repeats encountered. */
UNREP(1 << 7),
/** Unexpected sequencing encountered. */
UNSEQ(1 << 8);
private int value;
IPv6ExthdrFlags(int value) {
this.value = value;
}
/**
* Gets the value as an integer.
*
* @return the value as an integer
*/
public int getValue() {
return this.value;
}
}
}
......
......@@ -255,6 +255,10 @@ public class DefaultTrafficSelectorTest {
assertThat(selector, hasCriterionWithType(Type.MPLS_LABEL));
selector = DefaultTrafficSelector.builder()
.matchIPv6ExthdrFlags(Criterion.IPv6ExthdrFlags.NONEXT.getValue()).build();
assertThat(selector, hasCriterionWithType(Type.IPV6_EXTHDR));
selector = DefaultTrafficSelector.builder()
.matchLambda(shortValue).build();
assertThat(selector, hasCriterionWithType(Type.OCH_SIGID));
......
......@@ -192,14 +192,32 @@ public class CriteriaTest {
Criterion sameAsMatchMpls1 = Criteria.matchMplsLabel(mpls1);
Criterion matchMpls2 = Criteria.matchMplsLabel(mpls2);
int ipv6ExthdrFlags1 =
Criterion.IPv6ExthdrFlags.NONEXT.getValue() |
Criterion.IPv6ExthdrFlags.ESP.getValue() |
Criterion.IPv6ExthdrFlags.AUTH.getValue() |
Criterion.IPv6ExthdrFlags.DEST.getValue() |
Criterion.IPv6ExthdrFlags.FRAG.getValue() |
Criterion.IPv6ExthdrFlags.ROUTER.getValue() |
Criterion.IPv6ExthdrFlags.HOP.getValue() |
Criterion.IPv6ExthdrFlags.UNREP.getValue();
int ipv6ExthdrFlags2 = ipv6ExthdrFlags1 |
Criterion.IPv6ExthdrFlags.UNSEQ.getValue();
Criterion matchIpv6ExthdrFlags1 =
Criteria.matchIPv6ExthdrFlags(ipv6ExthdrFlags1);
Criterion sameAsMatchIpv6ExthdrFlags1 =
Criteria.matchIPv6ExthdrFlags(ipv6ExthdrFlags1);
Criterion matchIpv6ExthdrFlags2 =
Criteria.matchIPv6ExthdrFlags(ipv6ExthdrFlags2);
int lambda1 = 1;
int lambda2 = 2;
Criterion matchLambda1 = Criteria.matchLambda(lambda1);
Criterion sameAsMatchLambda1 = Criteria.matchLambda(lambda1);
Criterion matchLambda2 = Criteria.matchLambda(lambda2);
int signalLambda1 = 1;
int signalLambda2 = 2;
short signalLambda1 = 1;
short signalLambda2 = 2;
Criterion matchSignalLambda1 = Criteria.matchOpticalSignalType(signalLambda1);
Criterion sameAsMatchSignalLambda1 = Criteria.matchOpticalSignalType(signalLambda1);
Criterion matchSignalLambda2 = Criteria.matchOpticalSignalType(signalLambda2);
......@@ -256,6 +274,7 @@ public class CriteriaTest {
assertThatClassIsImmutable(Criteria.IPv6NDTargetAddressCriterion.class);
assertThatClassIsImmutable(Criteria.IPv6NDLinkLayerAddressCriterion.class);
assertThatClassIsImmutable(Criteria.MplsCriterion.class);
assertThatClassIsImmutable(Criteria.IPv6ExthdrFlagsCriterion.class);
assertThatClassIsImmutable(Criteria.LambdaCriterion.class);
assertThatClassIsImmutable(Criteria.OpticalSignalTypeCriterion.class);
}
......@@ -952,6 +971,35 @@ public class CriteriaTest {
.testEquals();
}
// IPv6ExthdrFlagsCriterion class
/**
* Test the matchIPv6ExthdrFlags method.
*/
@Test
public void testMatchIPv6ExthdrFlagsMethod() {
Criterion matchExthdrFlags =
Criteria.matchIPv6ExthdrFlags(ipv6ExthdrFlags1);
Criteria.IPv6ExthdrFlagsCriterion exthdrFlagsCriterion =
checkAndConvert(matchExthdrFlags,
Criterion.Type.IPV6_EXTHDR,
Criteria.IPv6ExthdrFlagsCriterion.class);
assertThat(exthdrFlagsCriterion.exthdrFlags(),
is(equalTo(ipv6ExthdrFlags1)));
}
/**
* Test the equals() method of the IPv6ExthdrFlagsCriterion class.
*/
@Test
public void testIPv6ExthdrFlagsCriterionEquals() {
new EqualsTester()
.addEqualityGroup(matchIpv6ExthdrFlags1,
sameAsMatchIpv6ExthdrFlags1)
.addEqualityGroup(matchIpv6ExthdrFlags2)
.testEquals();
}
// LambdaCriterion class
/**
......
......@@ -410,7 +410,6 @@ public class FlowEntryBuilder {
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());
......@@ -419,13 +418,11 @@ public class FlowEntryBuilder {
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());
......@@ -434,7 +431,6 @@ public class FlowEntryBuilder {
match.get(MatchField.IPV4_DST).getInt(),
Ip4Prefix.MAX_MASK_LENGTH);
}
builder.matchIPDst(ip4Prefix);
break;
case TCP_SRC:
......@@ -519,6 +515,10 @@ public class FlowEntryBuilder {
builder.matchMplsLabel((int) match.get(MatchField.MPLS_LABEL)
.getValue());
break;
case IPV6_EXTHDR:
builder.matchIPv6ExthdrFlags((int) match.get(MatchField.IPV6_EXTHDR)
.getValue());
break;
case OCH_SIGID:
builder.matchLambda(match.get(MatchField.OCH_SIGID).getChannelNumber());
break;
......@@ -539,5 +539,4 @@ public class FlowEntryBuilder {
}
return builder.build();
}
}
......
......@@ -67,6 +67,7 @@ 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.U8;
import org.projectfloodlight.openflow.types.VlanPcp;
......@@ -363,6 +364,12 @@ public abstract class FlowModBuilder {
Criteria.MplsCriterion mp = (Criteria.MplsCriterion) c;
mBuilder.setExact(MatchField.MPLS_LABEL, U32.of(mp.label()));
break;
case IPV6_EXTHDR:
Criteria.IPv6ExthdrFlagsCriterion exthdrFlagsCriterion =
(Criteria.IPv6ExthdrFlagsCriterion) c;
mBuilder.setExact(MatchField.IPV6_EXTHDR,
U16.of(exthdrFlagsCriterion.exthdrFlags()));
break;
case OCH_SIGID:
LambdaCriterion lc = (LambdaCriterion) c;
mBuilder.setExact(MatchField.OCH_SIGID,
......@@ -373,14 +380,13 @@ public abstract class FlowModBuilder {
Criteria.OpticalSignalTypeCriterion sc =
(Criteria.OpticalSignalTypeCriterion) c;
mBuilder.setExact(MatchField.OCH_SIGTYPE,
U8.of((short) sc.signalType()));
U8.of(sc.signalType()));
break;
case ARP_OP:
case ARP_SHA:
case ARP_SPA:
case ARP_THA:
case ARP_TPA:
case IPV6_EXTHDR:
case MPLS_BOS:
case MPLS_TC:
case PBB_ISID:
......
......@@ -71,6 +71,7 @@ public final class CriterionCodec extends JsonCodec<Criterion> {
formatMap.put(Criterion.Type.IPV6_ND_SLL, new FormatV6NDTll());
formatMap.put(Criterion.Type.IPV6_ND_TLL, new FormatV6NDTll());
formatMap.put(Criterion.Type.MPLS_LABEL, new FormatMplsLabel());
formatMap.put(Criterion.Type.IPV6_EXTHDR, new FormatIpV6Exthdr());
formatMap.put(Criterion.Type.OCH_SIGID, new FormatOchSigId());
formatMap.put(Criterion.Type.OCH_SIGTYPE, new FormatOchSigType());
......@@ -84,7 +85,6 @@ public final class CriterionCodec extends JsonCodec<Criterion> {
formatMap.put(Criterion.Type.MPLS_BOS, new FormatUnknown());
formatMap.put(Criterion.Type.PBB_ISID, new FormatUnknown());
formatMap.put(Criterion.Type.TUNNEL_ID, new FormatUnknown());
formatMap.put(Criterion.Type.IPV6_EXTHDR, new FormatUnknown());
formatMap.put(Criterion.Type.UNASSIGNED_40, new FormatUnknown());
formatMap.put(Criterion.Type.PBB_UCA, new FormatUnknown());
formatMap.put(Criterion.Type.TCP_FLAGS, new FormatUnknown());
......@@ -289,6 +289,15 @@ public final class CriterionCodec extends JsonCodec<Criterion> {
}
}
private static class FormatIpV6Exthdr implements CriterionTypeFormatter {
@Override
public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
final Criteria.IPv6ExthdrFlagsCriterion exthdrCriterion =
(Criteria.IPv6ExthdrFlagsCriterion) criterion;
return root.put("exthdrFlags", exthdrCriterion.exthdrFlags());
}
}
private static class FormatOchSigId implements CriterionTypeFormatter {
@Override
public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
......
......@@ -407,6 +407,27 @@ public class CriterionCodecTest {
}
/**
* Tests IPv6 Extension Header pseudo-field flags criterion.
*/
@Test
public void matchIPv6ExthdrFlagsTest() {
int exthdrFlags =
Criterion.IPv6ExthdrFlags.NONEXT.getValue() |
Criterion.IPv6ExthdrFlags.ESP.getValue() |
Criterion.IPv6ExthdrFlags.AUTH.getValue() |
Criterion.IPv6ExthdrFlags.DEST.getValue() |
Criterion.IPv6ExthdrFlags.FRAG.getValue() |
Criterion.IPv6ExthdrFlags.ROUTER.getValue() |
Criterion.IPv6ExthdrFlags.HOP.getValue() |
Criterion.IPv6ExthdrFlags.UNREP.getValue() |
Criterion.IPv6ExthdrFlags.UNSEQ.getValue();
Criterion criterion = Criteria.matchIPv6ExthdrFlags(exthdrFlags);
ObjectNode result = criterionCodec.encode(criterion, context);
assertThat(result.get("type").textValue(), is(criterion.type().toString()));
assertThat(result.get("exthdrFlags").asInt(), is(exthdrFlags));
}
/**
* Tests lambda criterion.
*/
@Test
......@@ -422,10 +443,10 @@ public class CriterionCodecTest {
*/
@Test
public void matchOpticalSignalTypeTest() {
Criterion criterion = Criteria.matchOpticalSignalType((short) 40000);
Criterion criterion = Criteria.matchOpticalSignalType((byte) 250);
ObjectNode result = criterionCodec.encode(criterion, context);
assertThat(result.get("type").textValue(), is(criterion.type().toString()));
assertThat(result.get("signalType").asInt(), is(40000));
assertThat(result.get("signalType").asInt(), is(250));
}
}
......
......@@ -294,6 +294,18 @@ public final class CriterionJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNo
}
break;
case IPV6_EXTHDR:
final Criteria.IPv6ExthdrFlagsCriterion exthdrCriterion =
(Criteria.IPv6ExthdrFlagsCriterion) criterion;
final int exthdrFlags = exthdrCriterion.exthdrFlags();
final int jsonExthdrFlags =
jsonCriterion.get("exthdrFlags").intValue();
if (exthdrFlags != jsonExthdrFlags) {
description.appendText("exthdrFlags was " + Long.toHexString(jsonExthdrFlags));
return false;
}
break;
case OCH_SIGID:
final Criteria.LambdaCriterion lambdaCriterion =
(Criteria.LambdaCriterion) criterion;
......@@ -308,10 +320,10 @@ public final class CriterionJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNo
case OCH_SIGTYPE:
final Criteria.OpticalSignalTypeCriterion opticalSignalTypeCriterion =
(Criteria.OpticalSignalTypeCriterion) criterion;
final int signalType = opticalSignalTypeCriterion.signalType();
final int jsonSignalType = jsonCriterion.get("signalType").intValue();
final short signalType = opticalSignalTypeCriterion.signalType();
final short jsonSignalType = jsonCriterion.get("signalType").shortValue();
if (signalType != jsonSignalType) {
description.appendText("signal type was " + Integer.toString(signalType));
description.appendText("signal type was " + Short.toString(signalType));
return false;
}
break;
......