Pavlin Radoslavov

Implement some of the missing IPv6 flowmod treatments

Work toward ONOS-509

The following treatments are added/implemented:
  - IPV6_SRC
  - IPV6_DST
  - IPV6_FLABEL

Also:
 - Renamed L3ModificationInstruction.L3SubType.IP_SRC and IP_DST
   to IPV4_SRC and IPV4_DST (for naming consistency).
 - Few minor fixes in related code: Javadocs, comments, log messages,
   and IP address usage.

Change-Id: I551056f767a37e7cb6ae7d79f4a3929183500b57
......@@ -120,7 +120,7 @@ public interface TrafficTreatment {
public Builder setIpDst(IpAddress addr);
/**
* Decrease the TTL in IP header by one.
* Decrement the TTL in IP header by one.
*
* @return a treatment builder
*/
......
......@@ -29,6 +29,7 @@ import org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction.L3SubType;
import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModTtlInstruction;
import org.onlab.packet.Ethernet;
......@@ -144,24 +145,59 @@ public final class Instructions {
public static L2ModificationInstruction decMplsTtl() {
return new ModMplsTtlInstruction();
}
/**
* Creates a L3 src modification.
* @param addr the ip address to modify to.
* Creates a L3 IPv4 src modification.
*
* @param addr the IPv4 address to modify to
* @return a L3 modification
*/
public static L3ModificationInstruction modL3Src(IpAddress addr) {
checkNotNull(addr, "Src l3 address cannot be null");
return new ModIPInstruction(L3SubType.IP_SRC, addr);
checkNotNull(addr, "Src l3 IPv4 address cannot be null");
return new ModIPInstruction(L3SubType.IPV4_SRC, addr);
}
/**
* Creates a L3 dst modification.
* @param addr the ip address to modify to.
* Creates a L3 IPv4 dst modification.
*
* @param addr the IPv4 address to modify to
* @return a L3 modification
*/
public static L3ModificationInstruction modL3Dst(IpAddress addr) {
checkNotNull(addr, "Dst l3 address cannot be null");
return new ModIPInstruction(L3SubType.IP_DST, addr);
checkNotNull(addr, "Dst l3 IPv4 address cannot be null");
return new ModIPInstruction(L3SubType.IPV4_DST, addr);
}
/**
* Creates a L3 IPv6 src modification.
*
* @param addr the IPv6 address to modify to
* @return a L3 modification
*/
public static L3ModificationInstruction modL3IPv6Src(IpAddress addr) {
checkNotNull(addr, "Src l3 IPv6 address cannot be null");
return new ModIPInstruction(L3SubType.IPV6_SRC, addr);
}
/**
* Creates a L3 IPv6 dst modification.
*
* @param addr the IPv6 address to modify to
* @return a L3 modification
*/
public static L3ModificationInstruction modL3IPv6Dst(IpAddress addr) {
checkNotNull(addr, "Dst l3 IPv6 address cannot be null");
return new ModIPInstruction(L3SubType.IPV6_DST, addr);
}
/**
* Creates a L3 IPv6 Flow Label modification.
*
* @param flowLabel the IPv6 flow label to modify to (20 bits)
* @return a L3 modification
*/
public static L3ModificationInstruction modL3IPv6FlowLabel(int flowLabel) {
return new ModIPv6FlowLabelInstruction(flowLabel);
}
/**
......
......@@ -31,17 +31,32 @@ public abstract class L3ModificationInstruction implements Instruction {
*/
public enum L3SubType {
/**
* Ether src modification.
* IPv4 src modification.
*/
IP_SRC,
IPV4_SRC,
/**
* Ether dst modification.
* IPv4 dst modification.
*/
IP_DST,
IPV4_DST,
/**
* Decrease TTL.
* IPv6 src modification.
*/
IPV6_SRC,
/**
* IPv6 dst modification.
*/
IPV6_DST,
/**
* IPv6 flow label modification.
*/
IPV6_FLABEL,
/**
* Decrement TTL.
*/
DEC_TTL,
......@@ -120,6 +135,65 @@ public abstract class L3ModificationInstruction implements Instruction {
}
/**
* Represents a L3 IPv6 Flow Label (RFC 6437) modification instruction
* (20 bits unsigned integer).
*/
public static final class ModIPv6FlowLabelInstruction
extends L3ModificationInstruction {
private static final int MASK = 0xfffff;
private final int flowLabel; // IPv6 flow label: 20 bits
/**
* Constructor.
*
* flowLabel the IPv6 flow label to set in the treatment (20 bits)
*/
public ModIPv6FlowLabelInstruction(int flowLabel) {
this.flowLabel = flowLabel & MASK;
}
@Override
public L3SubType subtype() {
return L3SubType.IPV6_FLABEL;
}
/**
* Gets the IPv6 flow label to set in the treatment.
*
* @return the IPv6 flow label to set in the treatment (20 bits)
*/
public int flowLabel() {
return this.flowLabel;
}
@Override
public String toString() {
return toStringHelper(subtype().toString())
.add("flowLabel", Long.toHexString(flowLabel)).toString();
}
@Override
public int hashCode() {
return Objects.hash(type(), subtype(), flowLabel);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof ModIPv6FlowLabelInstruction) {
ModIPv6FlowLabelInstruction that =
(ModIPv6FlowLabelInstruction) obj;
return Objects.equals(flowLabel, that.flowLabel) &&
Objects.equals(this.type(), that.type()) &&
Objects.equals(this.subtype(), that.subtype());
}
return false;
}
}
/**
* Represents a L3 TTL modification instruction.
*/
public static final class ModTtlInstruction extends L3ModificationInstruction {
......
......@@ -18,7 +18,6 @@ package org.onosproject.net.flow.instructions;
import org.junit.Test;
import org.onosproject.net.PortNumber;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
......@@ -94,6 +93,7 @@ public class InstructionsTest {
assertThatClassIsImmutable(L2ModificationInstruction.ModVlanIdInstruction.class);
assertThatClassIsImmutable(L2ModificationInstruction.ModVlanPcpInstruction.class);
assertThatClassIsImmutable(L3ModificationInstruction.ModIPInstruction.class);
assertThatClassIsImmutable(L3ModificationInstruction.ModIPv6FlowLabelInstruction.class);
assertThatClassIsImmutable(L2ModificationInstruction.ModMplsLabelInstruction.class);
assertThatClassIsImmutable(L2ModificationInstruction.PushHeaderInstructions.class);
}
......@@ -377,29 +377,40 @@ public class InstructionsTest {
is(not(equalTo(modVlanPcp2.hashCode()))));
}
// ModIPerInstruction
private static final String IP1 = "1.2.3.4/24";
private static final String IP2 = "5.6.7.8/24";
private IpAddress ip1 = IpPrefix.valueOf(IP1).address();
private IpAddress ip2 = IpPrefix.valueOf(IP2).address();
private final Instruction modIPInstruction1 = Instructions.modL3Src(ip1);
private final Instruction sameAsModIPInstruction1 = Instructions.modL3Src(ip1);
private final Instruction modIPInstruction2 = Instructions.modL3Src(ip2);
// ModIPInstruction
private static final String IP41 = "1.2.3.4";
private static final String IP42 = "5.6.7.8";
private IpAddress ip41 = IpAddress.valueOf(IP41);
private IpAddress ip42 = IpAddress.valueOf(IP42);
private final Instruction modIPInstruction1 = Instructions.modL3Src(ip41);
private final Instruction sameAsModIPInstruction1 = Instructions.modL3Src(ip41);
private final Instruction modIPInstruction2 = Instructions.modL3Src(ip42);
private static final String IP61 = "1111::2222";
private static final String IP62 = "3333::4444";
private IpAddress ip61 = IpAddress.valueOf(IP61);
private IpAddress ip62 = IpAddress.valueOf(IP62);
private final Instruction modIPv6Instruction1 =
Instructions.modL3IPv6Src(ip61);
private final Instruction sameAsModIPv6Instruction1 =
Instructions.modL3IPv6Src(ip61);
private final Instruction modIPv6Instruction2 =
Instructions.modL3IPv6Src(ip62);
/**
* Test the modL3Src method.
*/
@Test
public void testModL3SrcMethod() {
final Instruction instruction = Instructions.modL3Src(ip1);
final Instruction instruction = Instructions.modL3Src(ip41);
final L3ModificationInstruction.ModIPInstruction modIPInstruction =
checkAndConvert(instruction,
Instruction.Type.L3MODIFICATION,
L3ModificationInstruction.ModIPInstruction.class);
assertThat(modIPInstruction.ip(), is(equalTo(ip1)));
assertThat(modIPInstruction.ip(), is(equalTo(ip41)));
assertThat(modIPInstruction.subtype(),
is(equalTo(L3ModificationInstruction.L3SubType.IP_SRC)));
is(equalTo(L3ModificationInstruction.L3SubType.IPV4_SRC)));
}
/**
......@@ -407,20 +418,49 @@ public class InstructionsTest {
*/
@Test
public void testModL3DstMethod() {
final Instruction instruction = Instructions.modL3Dst(ip1);
final Instruction instruction = Instructions.modL3Dst(ip41);
final L3ModificationInstruction.ModIPInstruction modIPInstruction =
checkAndConvert(instruction,
Instruction.Type.L3MODIFICATION,
L3ModificationInstruction.ModIPInstruction.class);
assertThat(modIPInstruction.ip(), is(equalTo(ip1)));
assertThat(modIPInstruction.ip(), is(equalTo(ip41)));
assertThat(modIPInstruction.subtype(),
is(equalTo(L3ModificationInstruction.L3SubType.IP_DST)));
is(equalTo(L3ModificationInstruction.L3SubType.IPV4_DST)));
}
/**
* Test the equals() method of the ModEtherInstruction class.
* Test the modL3IPv6Src method.
*/
@Test
public void testModL3IPv6SrcMethod() {
final Instruction instruction = Instructions.modL3IPv6Src(ip61);
final L3ModificationInstruction.ModIPInstruction modIPInstruction =
checkAndConvert(instruction,
Instruction.Type.L3MODIFICATION,
L3ModificationInstruction.ModIPInstruction.class);
assertThat(modIPInstruction.ip(), is(equalTo(ip61)));
assertThat(modIPInstruction.subtype(),
is(equalTo(L3ModificationInstruction.L3SubType.IPV6_SRC)));
}
/**
* Test the modL3IPv6Dst method.
*/
@Test
public void testModL3IPv6DstMethod() {
final Instruction instruction = Instructions.modL3IPv6Dst(ip61);
final L3ModificationInstruction.ModIPInstruction modIPInstruction =
checkAndConvert(instruction,
Instruction.Type.L3MODIFICATION,
L3ModificationInstruction.ModIPInstruction.class);
assertThat(modIPInstruction.ip(), is(equalTo(ip61)));
assertThat(modIPInstruction.subtype(),
is(equalTo(L3ModificationInstruction.L3SubType.IPV6_DST)));
}
/**
* Test the equals() method of the ModIPInstruction class.
*/
@Test
public void testModIPInstructionEquals() throws Exception {
checkEqualsAndToString(modIPInstruction1,
......@@ -429,9 +469,8 @@ public class InstructionsTest {
}
/**
* Test the hashCode() method of the ModEtherInstruction class.
* Test the hashCode() method of the ModIPInstruction class.
*/
@Test
public void testModIPInstructionHashCode() {
assertThat(modIPInstruction1.hashCode(),
......@@ -440,6 +479,54 @@ public class InstructionsTest {
is(not(equalTo(modIPInstruction2.hashCode()))));
}
private final int flowLabel1 = 0x11111;
private final int flowLabel2 = 0x22222;
private final Instruction modIPv6FlowLabelInstruction1 =
Instructions.modL3IPv6FlowLabel(flowLabel1);
private final Instruction sameAsModIPv6FlowLabelInstruction1 =
Instructions.modL3IPv6FlowLabel(flowLabel1);
private final Instruction modIPv6FlowLabelInstruction2 =
Instructions.modL3IPv6FlowLabel(flowLabel2);
/**
* Test the modL3IPv6FlowLabel method.
*/
@Test
public void testModL3IPv6FlowLabelMethod() {
final Instruction instruction =
Instructions.modL3IPv6FlowLabel(flowLabel1);
final L3ModificationInstruction.ModIPv6FlowLabelInstruction
modIPv6FlowLabelInstruction =
checkAndConvert(instruction,
Instruction.Type.L3MODIFICATION,
L3ModificationInstruction.ModIPv6FlowLabelInstruction.class);
assertThat(modIPv6FlowLabelInstruction.flowLabel(),
is(equalTo(flowLabel1)));
assertThat(modIPv6FlowLabelInstruction.subtype(),
is(equalTo(L3ModificationInstruction.L3SubType.IPV6_FLABEL)));
}
/**
* Test the equals() method of the ModIPv6FlowLabelInstruction class.
*/
@Test
public void testModIPv6FlowLabelInstructionEquals() throws Exception {
checkEqualsAndToString(modIPv6FlowLabelInstruction1,
sameAsModIPv6FlowLabelInstruction1,
modIPv6FlowLabelInstruction2);
}
/**
* Test the hashCode() method of the ModIPv6FlowLabelInstruction class.
*/
@Test
public void testModIPv6FlowLabelInstructionHashCode() {
assertThat(modIPv6FlowLabelInstruction1.hashCode(),
is(equalTo(sameAsModIPv6FlowLabelInstruction1.hashCode())));
assertThat(modIPv6FlowLabelInstruction1.hashCode(),
is(not(equalTo(modIPv6FlowLabelInstruction2.hashCode()))));
}
private Instruction modMplsLabelInstruction1 = Instructions.modMplsLabel(1);
private Instruction sameAsModMplsLabelInstruction1 = Instructions.modMplsLabel(1);
private Instruction modMplsLabelInstruction2 = Instructions.modMplsLabel(2);
......@@ -463,7 +550,6 @@ public class InstructionsTest {
* Test the equals(), hashCode and toString() methods of the
* ModMplsLabelInstruction class.
*/
@Test
public void testModMplsLabelInstructionEquals() throws Exception {
checkEqualsAndToString(modMplsLabelInstruction1,
......
......@@ -257,6 +257,7 @@ public final class KryoNamespaces {
L3ModificationInstruction.class,
L3ModificationInstruction.L3SubType.class,
L3ModificationInstruction.ModIPInstruction.class,
L3ModificationInstruction.ModIPv6FlowLabelInstruction.class,
RoleInfo.class,
FlowRuleBatchEvent.class,
FlowRuleBatchEvent.Type.class,
......
......@@ -176,14 +176,14 @@ public class FlowModBuilderVer10 extends FlowModBuilder {
ModIPInstruction ip;
Ip4Address ip4;
switch (l3m.subtype()) {
case IP_DST:
case IPV4_SRC:
ip = (ModIPInstruction) i;
ip4 = ip.ip().getIp4Address();
return factory().actions().setNwDst(IPv4Address.of(ip4.toInt()));
case IP_SRC:
return factory().actions().setNwSrc(IPv4Address.of(ip4.toInt()));
case IPV4_DST:
ip = (ModIPInstruction) i;
ip4 = ip.ip().getIp4Address();
return factory().actions().setNwSrc(IPv4Address.of(ip4.toInt()));
return factory().actions().setNwDst(IPv4Address.of(ip4.toInt()));
default:
log.warn("Unimplemented action type {}.", l3m.subtype());
break;
......
......@@ -16,6 +16,7 @@
package org.onosproject.provider.of.flow.impl;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficTreatment;
......@@ -32,6 +33,7 @@ import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPc
import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
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.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFlowAdd;
import org.projectfloodlight.openflow.protocol.OFFlowDelete;
......@@ -45,6 +47,8 @@ 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.OFBufferId;
import org.projectfloodlight.openflow.types.OFGroup;
......@@ -267,17 +271,34 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
L3ModificationInstruction l3m = (L3ModificationInstruction) i;
ModIPInstruction ip;
Ip4Address ip4;
Ip6Address ip6;
OFOxm<?> oxm = null;
switch (l3m.subtype()) {
case IP_DST:
case IPV4_SRC:
ip = (ModIPInstruction) i;
ip4 = ip.ip().getIp4Address();
oxm = factory().oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
oxm = factory().oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
break;
case IP_SRC:
case IPV4_DST:
ip = (ModIPInstruction) i;
ip4 = ip.ip().getIp4Address();
oxm = factory().oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
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();
......
......@@ -16,6 +16,7 @@
package org.onosproject.provider.of.group.impl;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onosproject.core.GroupId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.TrafficTreatment;
......@@ -39,6 +40,8 @@ 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.OFGroup;
import org.projectfloodlight.openflow.types.OFPort;
......@@ -284,17 +287,34 @@ public final class GroupModBuilder {
L3ModificationInstruction l3m = (L3ModificationInstruction) i;
L3ModificationInstruction.ModIPInstruction ip;
Ip4Address ip4;
Ip6Address ip6;
OFOxm<?> oxm = null;
switch (l3m.subtype()) {
case IP_DST:
case IPV4_SRC:
ip = (L3ModificationInstruction.ModIPInstruction) i;
ip4 = ip.ip().getIp4Address();
oxm = factory.oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
oxm = factory.oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
break;
case IP_SRC:
case IPV4_DST:
ip = (L3ModificationInstruction.ModIPInstruction) i;
ip4 = ip.ip().getIp4Address();
oxm = factory.oxms().ipv4Src(IPv4Address.of(ip4.toInt()));
oxm = factory.oxms().ipv4Dst(IPv4Address.of(ip4.toInt()));
break;
case IPV6_SRC:
ip = (L3ModificationInstruction.ModIPInstruction) i;
ip6 = ip.ip().getIp6Address();
oxm = factory.oxms().ipv6Src(IPv6Address.of(ip6.toOctets()));
break;
case IPV6_DST:
ip = (L3ModificationInstruction.ModIPInstruction) i;
ip6 = ip.ip().getIp6Address();
oxm = factory.oxms().ipv6Dst(IPv6Address.of(ip6.toOctets()));
break;
case IPV6_FLABEL:
L3ModificationInstruction.ModIPv6FlowLabelInstruction flowLabelInstruction =
(L3ModificationInstruction.ModIPv6FlowLabelInstruction) i;
int flowLabel = flowLabelInstruction.flowLabel();
oxm = factory.oxms().ipv6Flabel(IPv6FlowLabel.of(flowLabel));
break;
case DEC_TTL:
return factory.actions().decNwTtl();
......
......@@ -117,13 +117,22 @@ public final class InstructionCodec extends JsonCodec<Instruction> {
private void encodeL3(ObjectNode result, L3ModificationInstruction instruction) {
result.put("subtype", instruction.subtype().name());
switch (instruction.subtype()) {
case IP_SRC:
case IP_DST:
case IPV4_SRC:
case IPV4_DST:
case IPV6_SRC:
case IPV6_DST:
final L3ModificationInstruction.ModIPInstruction modIPInstruction =
(L3ModificationInstruction.ModIPInstruction) instruction;
result.put("ip", modIPInstruction.ip().toString());
break;
case IPV6_FLABEL:
final L3ModificationInstruction.ModIPv6FlowLabelInstruction
modFlowLabelInstruction =
(L3ModificationInstruction.ModIPv6FlowLabelInstruction) instruction;
result.put("flowLabel", modFlowLabelInstruction.flowLabel());
break;
default:
log.info("Cannot convert L3 subtype of {}", instruction.subtype());
break;
......
......@@ -17,8 +17,8 @@ package org.onosproject.codec.impl;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.codec.CodecContext;
......@@ -144,11 +144,11 @@ public class InstructionCodecTest {
}
/**
* Tests the encoding of mod ip instructions.
* Tests the encoding of mod IPv4 src instructions.
*/
@Test
public void modIPInstructionTest() {
final IpAddress ip = IpPrefix.valueOf("1.2.3.4/24").address();
public void modIPSrcInstructionTest() {
final Ip4Address ip = Ip4Address.valueOf("1.2.3.4");
final L3ModificationInstruction.ModIPInstruction instruction =
(L3ModificationInstruction.ModIPInstruction)
Instructions.modL3Src(ip);
......@@ -158,6 +158,62 @@ public class InstructionCodecTest {
}
/**
* Tests the encoding of mod IPv4 dst instructions.
*/
@Test
public void modIPDstInstructionTest() {
final Ip4Address ip = Ip4Address.valueOf("1.2.3.4");
final L3ModificationInstruction.ModIPInstruction instruction =
(L3ModificationInstruction.ModIPInstruction)
Instructions.modL3Dst(ip);
final ObjectNode instructionJson =
instructionCodec.encode(instruction, context);
assertThat(instructionJson, matchesInstruction(instruction));
}
/**
* Tests the encoding of mod IPv6 src instructions.
*/
@Test
public void modIPv6SrcInstructionTest() {
final Ip6Address ip = Ip6Address.valueOf("1111::2222");
final L3ModificationInstruction.ModIPInstruction instruction =
(L3ModificationInstruction.ModIPInstruction)
Instructions.modL3IPv6Src(ip);
final ObjectNode instructionJson =
instructionCodec.encode(instruction, context);
assertThat(instructionJson, matchesInstruction(instruction));
}
/**
* Tests the encoding of mod IPv6 dst instructions.
*/
@Test
public void modIPv6DstInstructionTest() {
final Ip6Address ip = Ip6Address.valueOf("1111::2222");
final L3ModificationInstruction.ModIPInstruction instruction =
(L3ModificationInstruction.ModIPInstruction)
Instructions.modL3IPv6Dst(ip);
final ObjectNode instructionJson =
instructionCodec.encode(instruction, context);
assertThat(instructionJson, matchesInstruction(instruction));
}
/**
* Tests the encoding of mod IPv6 flow label instructions.
*/
@Test
public void modIPv6FlowLabelInstructionTest() {
final int flowLabel = 0xfffff;
final L3ModificationInstruction.ModIPv6FlowLabelInstruction instruction =
(L3ModificationInstruction.ModIPv6FlowLabelInstruction)
Instructions.modL3IPv6FlowLabel(flowLabel);
final ObjectNode instructionJson =
instructionCodec.encode(instruction, context);
assertThat(instructionJson, matchesInstruction(instruction));
}
/**
* Tests the encoding of mod MPLS label instructions.
*/
@Test
......
......@@ -41,6 +41,7 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
* Matches the contents of a push header instruction.
*
* @param instructionJson JSON instruction to match
* @param description Description object used for recording errors
* @return true if contents match, false otherwise
*/
private boolean matchPushHeaderInstruction(JsonNode instructionJson,
......@@ -77,6 +78,7 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
* Matches the contents of an output instruction.
*
* @param instructionJson JSON instruction to match
* @param description Description object used for recording errors
* @return true if contents match, false otherwise
*/
private boolean matchOutputInstruction(JsonNode instructionJson,
......@@ -102,6 +104,7 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
* Matches the contents of a mod lambda instruction.
*
* @param instructionJson JSON instruction to match
* @param description Description object used for recording errors
* @return true if contents match, false otherwise
*/
private boolean matchModLambdaInstruction(JsonNode instructionJson,
......@@ -133,6 +136,7 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
* Matches the contents of a mod Ethernet instruction.
*
* @param instructionJson JSON instruction to match
* @param description Description object used for recording errors
* @return true if contents match, false otherwise
*/
private boolean matchModEtherInstruction(JsonNode instructionJson,
......@@ -165,6 +169,7 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
* Matches the contents of a mod vlan id instruction.
*
* @param instructionJson JSON instruction to match
* @param description Description object used for recording errors
* @return true if contents match, false otherwise
*/
private boolean matchModVlanIdInstruction(JsonNode instructionJson,
......@@ -197,6 +202,7 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
* Matches the contents of a mod vlan pcp instruction.
*
* @param instructionJson JSON instruction to match
* @param description Description object used for recording errors
* @return true if contents match, false otherwise
*/
private boolean matchModVlanPcpInstruction(JsonNode instructionJson,
......@@ -229,6 +235,7 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
* Matches the contents of a mod ip instruction.
*
* @param instructionJson JSON instruction to match
* @param description Description object used for recording errors
* @return true if contents match, false otherwise
*/
private boolean matchModIpInstruction(JsonNode instructionJson,
......@@ -258,9 +265,43 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
}
/**
* Matches the contents of a mod IPv6 Flow Label instruction.
*
* @param instructionJson JSON instruction to match
* @param description Description object used for recording errors
* @return true if contents match, false otherwise
*/
private boolean matchModIPv6FlowLabelInstruction(JsonNode instructionJson,
Description description) {
ModIPv6FlowLabelInstruction instructionToMatch =
(ModIPv6FlowLabelInstruction) instruction;
final String jsonSubtype = instructionJson.get("subtype").textValue();
if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
description.appendText("subtype was " + jsonSubtype);
return false;
}
final String jsonType = instructionJson.get("type").textValue();
if (!instructionToMatch.type().name().equals(jsonType)) {
description.appendText("type was " + jsonType);
return false;
}
final int jsonFlowLabel = instructionJson.get("flowLabel").intValue();
final int flowLabel = instructionToMatch.flowLabel();
if (flowLabel != jsonFlowLabel) {
description.appendText("IPv6 flow label was " + jsonFlowLabel);
return false;
}
return true;
}
/**
* Matches the contents of a mod MPLS label instruction.
*
* @param instructionJson JSON instruction to match
* @param description Description object used for recording errors
* @return true if contents match, false otherwise
*/
private boolean matchModMplsLabelInstruction(JsonNode instructionJson,
......@@ -282,7 +323,7 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
final int jsonLabel = instructionJson.get("label").intValue();
final int label = instructionToMatch.label();
if (label != jsonLabel) {
description.appendText("ip was " + jsonLabel);
description.appendText("MPLS label was " + jsonLabel);
return false;
}
......@@ -317,6 +358,9 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
return matchModVlanPcpInstruction(jsonInstruction, description);
} else if (instruction instanceof ModIPInstruction) {
return matchModIpInstruction(jsonInstruction, description);
} else if (instruction instanceof ModIPv6FlowLabelInstruction) {
return matchModIPv6FlowLabelInstruction(jsonInstruction,
description);
} else if (instruction instanceof ModMplsLabelInstruction) {
return matchModMplsLabelInstruction(jsonInstruction, description);
}
......