/*
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.openflowplugin.openflow.md.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.math.BigInteger;
import org.junit.Test;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlowBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlowBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmMatchType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.v10.grouping.MatchV10;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.aggregate._case.MultipartRequestAggregate;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.aggregate._case.MultipartRequestAggregateBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.flow._case.MultipartRequestFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.flow._case.MultipartRequestFlowBuilder;
public class FlowCreatorUtilTest {
private static final MacAddress macAddress = new MacAddress("00:00:00:00:00:00");
private static final Ipv4Address ipv4Address = new Ipv4Address("0.0.0.0");
/**
* Test method for {@link FlowCreatorUtil#setWildcardedFlowMatch(short version, MultipartRequestFlowBuilder flowBuilder)}.
*/
@Test
public void testSetWildcardedFlowMatch_1_0() {
MultipartRequestFlowBuilder multipartRequestFlowBuilder = new MultipartRequestFlowBuilder();
FlowCreatorUtil.setWildcardedFlowMatch(OFConstants.OFP_VERSION_1_0, multipartRequestFlowBuilder);
MultipartRequestFlow multipartRequestFlow = multipartRequestFlowBuilder.build();
assertMatch(multipartRequestFlow.getMatchV10());
multipartRequestFlowBuilder = new MultipartRequestFlowBuilder();
FlowCreatorUtil.setWildcardedFlowMatch(OFConstants.OFP_VERSION_1_3, multipartRequestFlowBuilder);
multipartRequestFlow = multipartRequestFlowBuilder.build();
assertMatch(multipartRequestFlow.getMatch());
}
/**
* Test method for {@link FlowCreatorUtil#setWildcardedFlowMatch(short version, MultipartRequestAggregateBuilder aggregateBuilder)}.
*/
@Test
public void testSetWildcardedFlowMatch_() {
MultipartRequestAggregateBuilder multipartRequestAggregateBuilder = new MultipartRequestAggregateBuilder();
FlowCreatorUtil.setWildcardedFlowMatch(OFConstants.OFP_VERSION_1_0, multipartRequestAggregateBuilder);
MultipartRequestAggregate multipartRequestAggregate = multipartRequestAggregateBuilder.build();
assertMatch(multipartRequestAggregate.getMatchV10());
multipartRequestAggregateBuilder = new MultipartRequestAggregateBuilder();
FlowCreatorUtil.setWildcardedFlowMatch(OFConstants.OFP_VERSION_1_3, multipartRequestAggregateBuilder);
multipartRequestAggregate = multipartRequestAggregateBuilder.build();
assertMatch(multipartRequestAggregate.getMatch());
}
/**
* Test method for
* {@link FlowCreatorUtil#canModifyFlow(OriginalFlow, UpdatedFlow, Short)}.
*/
@Test
public void testCanModifyFlow() {
final Short of10 = Short.valueOf(OFConstants.OFP_VERSION_1_0);
final Short of13 = Short.valueOf(OFConstants.OFP_VERSION_1_3);
final Short[] versions = {null, of10, of13};
final Boolean[] bools = {null, Boolean.TRUE, Boolean.FALSE};
final Integer defPri = Integer.valueOf(0x8000);
final Integer defIdle = Integer.valueOf(0);
final Integer defHard = Integer.valueOf(0);
final FlowModFlags defFlags = FlowModFlags.getDefaultInstance("sENDFLOWREM");
final FlowModFlags flags = new FlowModFlags(false, true, false, true, false);
final FlowCookie defCookie = new FlowCookie(BigInteger.ZERO);
final FlowCookie cookie = new FlowCookie(BigInteger.valueOf(0x12345L));
final FlowCookie cookie1 = new FlowCookie(BigInteger.valueOf(0x67890L));
final FlowCookie cookieMask = new FlowCookie(BigInteger.valueOf(0xffff00L));
for (final Short ver: versions) {
final OriginalFlowBuilder originalBuilder = new OriginalFlowBuilder();
final UpdatedFlowBuilder updatedBuilder = new UpdatedFlowBuilder();
canModifyFlowTest(true, originalBuilder, updatedBuilder, ver);
// Default value tests.
canModifyFlowTest(true,
new OriginalFlowBuilder().setPriority(defPri),
updatedBuilder, ver);
canModifyFlowTest(true, originalBuilder,
new UpdatedFlowBuilder().setPriority(defPri),
ver);
canModifyFlowTest(true,
new OriginalFlowBuilder().setIdleTimeout(defIdle),
updatedBuilder, ver);
canModifyFlowTest(true, originalBuilder,
new UpdatedFlowBuilder().setIdleTimeout(defIdle),
ver);
canModifyFlowTest(true,
new OriginalFlowBuilder().setHardTimeout(defHard),
updatedBuilder, ver);
canModifyFlowTest(true, originalBuilder,
new UpdatedFlowBuilder().setHardTimeout(defHard),
ver);
canModifyFlowTest(false,
new OriginalFlowBuilder().setFlags(defFlags),
updatedBuilder, ver);
canModifyFlowTest(false, originalBuilder,
new UpdatedFlowBuilder().setFlags(defFlags),
ver);
canModifyFlowTest(true,
new OriginalFlowBuilder().setCookie(defCookie),
updatedBuilder, ver);
canModifyFlowTest(true, originalBuilder,
new UpdatedFlowBuilder().setCookie(defCookie),
ver);
// Set non-default values.
canModifyFlowTest(true,
originalBuilder.setMatch(createMatch(0x800L)),
updatedBuilder.setMatch(createMatch(0x800L)),
ver);
canModifyFlowTest(true, originalBuilder.setIdleTimeout(600),
updatedBuilder.setIdleTimeout(600), ver);
canModifyFlowTest(true, originalBuilder.setHardTimeout(1200),
updatedBuilder.setHardTimeout(1200), ver);
canModifyFlowTest(true, originalBuilder.setPriority(100),
updatedBuilder.setPriority(100), ver);
canModifyFlowTest(true, originalBuilder.setFlags(flags),
updatedBuilder.setFlags(flags), ver);
canModifyFlowTest(true, originalBuilder.setCookie(cookie),
updatedBuilder.setCookie(cookie), ver);
final OriginalFlow org = originalBuilder.build();
final UpdatedFlow upd = updatedBuilder.build();
// Set different match.
final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match[] matches = {null, createMatch(0x86ddL)};
for (final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match m: matches) {
canModifyFlowTest(false, originalBuilder,
new UpdatedFlowBuilder(upd).setMatch(m),
ver);
canModifyFlowTest(false,
new OriginalFlowBuilder(org).setMatch(m),
updatedBuilder, ver);
}
// Set different idle-timeout, hard-timeout, priority.
final Integer[] integers = {null, Integer.valueOf(3600)};
for (final Integer i: integers) {
canModifyFlowTest(false, originalBuilder,
new UpdatedFlowBuilder(upd).setIdleTimeout(i),
ver);
canModifyFlowTest(false,
new OriginalFlowBuilder(org).setIdleTimeout(i),
updatedBuilder, ver);
canModifyFlowTest(false, originalBuilder,
new UpdatedFlowBuilder(upd).setHardTimeout(i),
ver);
canModifyFlowTest(false,
new OriginalFlowBuilder(org).setHardTimeout(i),
updatedBuilder, ver);
canModifyFlowTest(false, originalBuilder,
new UpdatedFlowBuilder(upd).setPriority(i),
ver);
canModifyFlowTest(false,
new OriginalFlowBuilder(org).setPriority(i),
updatedBuilder, ver);
}
// Set different FLOW_MOD flags.
final FlowModFlags[] flowModFlags = {
null,
defFlags,
new FlowModFlags(true, true, true, true, true),
};
for (final FlowModFlags f: flowModFlags) {
canModifyFlowTest(false, originalBuilder,
new UpdatedFlowBuilder(upd).setFlags(f),
ver);
canModifyFlowTest(false,
new OriginalFlowBuilder(org).setFlags(f),
updatedBuilder, ver);
}
// Set different cookie.
final FlowCookie[] cookies = {
null,
defCookie,
new FlowCookie(BigInteger.valueOf(0x123456L)),
};
for (final FlowCookie c: cookies) {
canModifyFlowTest(false, originalBuilder,
new UpdatedFlowBuilder(upd).setCookie(c),
ver);
canModifyFlowTest(false,
new OriginalFlowBuilder(org).setCookie(c),
updatedBuilder, ver);
}
// Cookie mask test.
// Cookie mask is used by OF13 non-strict MODIFY command.
updatedBuilder.setCookie(cookie1);
for (final Boolean strict: bools) {
updatedBuilder.setCookieMask(null).setStrict(strict);
canModifyFlowTest(false, originalBuilder, updatedBuilder, ver);
updatedBuilder.setCookieMask(defCookie);
canModifyFlowTest(false, originalBuilder, updatedBuilder, ver);
updatedBuilder.setCookieMask(cookieMask);
final boolean expected = (of13.equals(ver) &&
!Boolean.TRUE.equals(strict));
canModifyFlowTest(expected, originalBuilder, updatedBuilder,
ver);
}
}
}
/**
* Test method for
* {@link FlowCreatorUtil#equalsFlowModFlags(FlowModFlags, FlowModFlags)}.
*/
@Test
public void testEqualsFlowModFlags() {
final FlowModFlags[] defaults = {
null,
new FlowModFlags(false, false, false, false, false),
new FlowModFlags(false, null, false, null, Boolean.FALSE),
};
final FlowModFlags all = new FlowModFlags(true, true, true, true, true);
final FlowModFlags none = new FlowModFlags(null, null, null, null, null);
for (final FlowModFlags f: defaults) {
assertTrue(FlowCreatorUtil.
equalsFlowModFlags(f, (FlowModFlags)null));
assertTrue(FlowCreatorUtil.
equalsFlowModFlags((FlowModFlags)null, f));
assertFalse(FlowCreatorUtil.
equalsFlowModFlags((FlowModFlags)null, all));
assertFalse(FlowCreatorUtil.
equalsFlowModFlags(all, (FlowModFlags)null));
assertTrue(FlowCreatorUtil.
equalsFlowModFlags((FlowModFlags)null, none));
assertTrue(FlowCreatorUtil.
equalsFlowModFlags(none, (FlowModFlags)null));
}
final String[] bitNames = {
"cHECKOVERLAP",
"nOBYTCOUNTS",
"nOPKTCOUNTS",
"rESETCOUNTS",
"sENDFLOWREM"
};
int bit = 0;
for (final String name: bitNames) {
final FlowModFlags flags = FlowModFlags.getDefaultInstance(name);
assertFalse(FlowCreatorUtil.equalsFlowModFlags(flags, all));
assertFalse(FlowCreatorUtil.equalsFlowModFlags(all, flags));
assertFalse(FlowCreatorUtil.equalsFlowModFlags(flags, none));
assertFalse(FlowCreatorUtil.equalsFlowModFlags(none, flags));
for (final String nm: bitNames) {
final FlowModFlags f = FlowModFlags.getDefaultInstance(nm);
final boolean expected = nm.equals(name);
assertEquals(expected,
FlowCreatorUtil.equalsFlowModFlags(flags, f));
assertEquals(expected,
FlowCreatorUtil.equalsFlowModFlags(f, flags));
}
final boolean overlap = (bit == 0);
final boolean noByte = (bit == 1);
final boolean noPacket = (bit == 2);
final boolean reset = (bit == 3);
final boolean flowRem = (bit == 4);
FlowModFlags f =
new FlowModFlags(overlap, noByte, noPacket, reset, flowRem);
assertTrue(FlowCreatorUtil.equalsFlowModFlags(flags, f));
assertTrue(FlowCreatorUtil.equalsFlowModFlags(f, flags));
assertTrue(FlowCreatorUtil.
equalsFlowModFlags(f, new FlowModFlags(f)));
f = new FlowModFlags(!overlap, noByte, noPacket, reset, flowRem);
assertFalse(FlowCreatorUtil.equalsFlowModFlags(flags, f));
f = new FlowModFlags(overlap, !noByte, noPacket, reset, flowRem);
assertFalse(FlowCreatorUtil.equalsFlowModFlags(flags, f));
f = new FlowModFlags(overlap, noByte, !noPacket, reset, flowRem);
assertFalse(FlowCreatorUtil.equalsFlowModFlags(flags, f));
f = new FlowModFlags(overlap, noByte, noPacket, !reset, flowRem);
assertFalse(FlowCreatorUtil.equalsFlowModFlags(flags, f));
f = new FlowModFlags(overlap, noByte, noPacket, reset, !flowRem);
assertFalse(FlowCreatorUtil.equalsFlowModFlags(flags, f));
bit++;
}
}
/**
* Test method for
* {@link FlowCreatorUtil#equalsWithDefault(Object, Object, Object)}.
*/
@Test
public void testEqualsWithDefault() {
// Boolean
for (final Boolean def: new Boolean[]{Boolean.TRUE, Boolean.FALSE}) {
assertTrue(FlowCreatorUtil.equalsWithDefault(null, null, def));
assertTrue(FlowCreatorUtil.equalsWithDefault(def, null, def));
assertTrue(FlowCreatorUtil.equalsWithDefault(null, def, def));
final Boolean inv = Boolean.valueOf(!def.booleanValue());
assertFalse(FlowCreatorUtil.equalsWithDefault(null, inv, def));
assertFalse(FlowCreatorUtil.equalsWithDefault(inv, null, def));
}
// Integer
final Integer[] integers = {
Integer.valueOf(-100),
Integer.valueOf(0),
Integer.valueOf(100),
};
for (final Integer def: integers) {
final Integer same = new Integer(def.intValue());
assertTrue(FlowCreatorUtil.equalsWithDefault(null, null, def));
assertTrue(FlowCreatorUtil.equalsWithDefault(same, null, def));
assertTrue(FlowCreatorUtil.equalsWithDefault(null, same, def));
final Integer diff = new Integer(def.intValue() +1);
assertFalse(FlowCreatorUtil.equalsWithDefault(null, diff, def));
assertFalse(FlowCreatorUtil.equalsWithDefault(diff, null, def));
}
// String
final String[] strings = {
"",
"test string 1",
"test string 2",
};
for (final String def: strings) {
final String same = new String(def);
assertTrue(FlowCreatorUtil.equalsWithDefault(null, null, def));
assertTrue(FlowCreatorUtil.equalsWithDefault(same, null, def));
assertTrue(FlowCreatorUtil.equalsWithDefault(null, same, def));
final String diff = def + "-1";
assertFalse(FlowCreatorUtil.equalsWithDefault(null, diff, def));
assertFalse(FlowCreatorUtil.equalsWithDefault(diff, null, def));
}
}
private static void assertMatch (final Match match) {
assertTrue(match.getType().getClass().isInstance(OxmMatchType.class));
}
private static void assertMatch (final MatchV10 matchV10) {
assertEquals(matchV10.getDlDst(), macAddress);
assertEquals(matchV10.getDlSrc(), macAddress);
assertTrue(matchV10.getNwSrcMask().shortValue() == 0);
assertTrue(matchV10.getNwDstMask().shortValue() == 0);
assertTrue(matchV10.getInPort().intValue() == 0);
assertTrue(matchV10.getDlVlan().intValue() == 0);
assertTrue(matchV10.getDlVlanPcp().shortValue() == 0);
assertTrue(matchV10.getDlType().intValue() == 0);
assertTrue(matchV10.getNwTos().shortValue() == 0);
assertTrue(matchV10.getNwProto().shortValue() == 0);
assertEquals(matchV10.getNwSrc(), ipv4Address);
assertEquals(matchV10.getNwDst(), ipv4Address);
assertTrue(matchV10.getTpSrc().intValue() == 0);
assertTrue(matchV10.getTpDst().intValue() == 0);
}
/**
* Verify that {@link FlowCreatorUtil#canModifyFlow(OriginalFlow, UpdatedFlow, Short)}
* returns expected value.
*
* @param expected
* An expected return value.
* @param org
* A original flow builder that contains original flow to be tested.
* @param upd
* An updated flow builder that contains updated flow to be tested.
* @param version
* OpenFlow protocol version.
*/
private static void canModifyFlowTest (final boolean expected, final OriginalFlowBuilder org,
final UpdatedFlowBuilder upd, final Short version) {
final boolean result = FlowCreatorUtil.
canModifyFlow(org.build(), upd.build(), version);
assertEquals(expected, result);
}
/**
* Create a flow match that specifies ethernet type.
*
* @param etherType An ethernet type value.
* @return A flow match that specifies the given ethernet type.
*/
private static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match createMatch (final long etherType) {
final EthernetTypeBuilder ethType = new EthernetTypeBuilder().
setType(new EtherType(etherType));
final EthernetMatchBuilder ether = new EthernetMatchBuilder().
setEthernetType(ethType.build());
return new MatchBuilder().setEthernetMatch(ether.build()).build();
}
}