/*
* Copyright (c) 2013 Big Switch Networks, Inc.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package org.sdnplatform.forwarding;
import static org.junit.Assert.*;
import static org.easymock.EasyMock.*;
import org.junit.Before;
import org.junit.Test;
import org.sdnplatform.addressspace.IAddressSpaceManagerService;
import org.sdnplatform.core.ListenerContext;
import org.sdnplatform.core.module.ModuleContext;
import org.sdnplatform.devicemanager.SwitchPort;
import org.sdnplatform.forwarding.RewriteServiceImpl;
import org.sdnplatform.packet.Ethernet;
public class RewriteServiceImplTest {
protected ListenerContext cntx;
protected RewriteServiceImpl rw;
protected IAddressSpaceManagerService addressSpaceManager;
protected static Long[] macsToTest = new Long[] {
Long.MIN_VALUE, Long.MAX_VALUE, -35342513L,
(long)Integer.MIN_VALUE, (long)Integer.MAX_VALUE,
0L, 1L, 2L, 3L, -1L, -2L, -3L, 4549495L, 42L, 129329392L
};
@Before
public void setUp() throws Exception {
ModuleContext fmc = new ModuleContext();
cntx = new ListenerContext();
rw = new RewriteServiceImpl();
addressSpaceManager = createNiceMock(IAddressSpaceManagerService.class);
fmc.addService(IAddressSpaceManagerService.class, addressSpaceManager);
rw.init(fmc);
rw.startUp(fmc);
replay(addressSpaceManager);
}
@Test
public void testGetRuleFromContext() {
RewriteServiceImpl.RewriteRule rule;
RewriteServiceImpl.RewriteRule rule2;
assertNull(cntx.getStorage().get(RewriteServiceImpl.REWRITE_RULE));
rule = rw.getRuleFromContext(cntx);
assertSame(rule, cntx.getStorage().get(RewriteServiceImpl.REWRITE_RULE));
cntx.getStorage().clear();
rule2 = rw.getRuleFromContext(cntx);
assertNotSame(rule, rule2);
ListenerContext cntx1 = new ListenerContext();
ListenerContext cntx2 = new ListenerContext();
rule = rw.getRuleFromContext(cntx1);
rule2 = rw.getRuleFromContext(cntx2);
assertNotSame(rule, rule2);
rw.setIngressDstMac(1L, 11L, cntx1);
rw.setTransportVlan((short)42, cntx2);
assertEquals(Long.valueOf(1L), rule.origDstMac);
assertEquals(Long.valueOf(11L), rule.finalDstMac);
assertEquals(null, rule.transportVlan);
assertEquals(null, rule.origSrcMac);
assertEquals(null, rule.finalSrcMac);
assertEquals(null, rule.ttlDecrement);
assertEquals(null, rule2.origDstMac);
assertEquals(null, rule2.finalDstMac);
assertEquals(Short.valueOf((short)42) , rule2.transportVlan);
assertEquals(null, rule2.origSrcMac);
assertEquals(null, rule2.finalSrcMac);
assertEquals(null, rule2.ttlDecrement);
}
@Test
public void testGetRuleFromContextIfExists() {
RewriteServiceImpl.RewriteRule rule;
RewriteServiceImpl.RewriteRule rule2;
assertNull(cntx.getStorage().get(RewriteServiceImpl.REWRITE_RULE));
rule = rw.getRuleFromContextIfExists(cntx);
assertNull(cntx.getStorage().get(RewriteServiceImpl.REWRITE_RULE));
assertNull(rule);
rule2 = rw.getRuleFromContext(cntx);
assertSame(rule2, cntx.getStorage().get(RewriteServiceImpl.REWRITE_RULE));
rule = rw.getRuleFromContextIfExists(cntx);
assertSame(rule, rule2);
ListenerContext cntx1 = new ListenerContext();
ListenerContext cntx2 = new ListenerContext();
rule = rw.getRuleFromContextIfExists(cntx1);
rule2 = rw.getRuleFromContext(cntx2);
assertNull(rule);
assertNotNull(rule2);
rw.setIngressDstMac(1L, 11L, cntx1);
rw.setTransportVlan((short)42, cntx2);
rule = rw.getRuleFromContextIfExists(cntx1);
assertNotNull(rule);
assertEquals(Long.valueOf(1L), rule.origDstMac);
assertEquals(Long.valueOf(11L), rule.finalDstMac);
assertEquals(null, rule.transportVlan);
assertEquals(null, rule.origSrcMac);
assertEquals(null, rule.finalSrcMac);
assertEquals(null, rule.ttlDecrement);
assertEquals(null, rule2.origDstMac);
assertEquals(null, rule2.finalDstMac);
assertEquals(Short.valueOf((short)42) , rule2.transportVlan);
assertEquals(null, rule2.origSrcMac);
assertEquals(null, rule2.finalSrcMac);
assertEquals(null, rule2.ttlDecrement);
}
@Test
public void testHasRewriteRules() {
assertEquals(false, rw.hasRewriteRules(cntx));
// only vlan
rw.setTransportVlan((short)1, cntx);
assertEquals(true, rw.hasRewriteRules(cntx));
rw.clearTransportVlan(cntx);
assertEquals(false, rw.hasRewriteRules(cntx));
// only dstMac
rw.setIngressDstMac(1L, 11L, cntx);
assertEquals(true, rw.hasRewriteRules(cntx));
rw.clearIngressDstMac(cntx);
assertEquals(false, rw.hasRewriteRules(cntx));
// only srcMac
rw.setEgressSrcMac(21L, 31L, cntx);
assertEquals(true, rw.hasRewriteRules(cntx));
rw.clearEgressSrcMac(cntx);
assertEquals(false, rw.hasRewriteRules(cntx));
// only TTL decrement
rw.setTtlDecrement(1, cntx);
assertEquals(true, rw.hasRewriteRules(cntx));
rw.clearTtlDecrement(cntx);
assertEquals(false, rw.hasRewriteRules(cntx));
// all of them
// first we set all of them
rw.setTransportVlan((short)1, cntx);
assertEquals(true, rw.hasRewriteRules(cntx));
rw.setIngressDstMac(1L, 11L, cntx);
assertEquals(true, rw.hasRewriteRules(cntx));
rw.setEgressSrcMac(21L, 31L, cntx);
assertEquals(true, rw.hasRewriteRules(cntx));
rw.setTtlDecrement(1, cntx);
assertEquals(true, rw.hasRewriteRules(cntx));
// no we remove all of them
rw.clearTransportVlan(cntx);
assertEquals(true, rw.hasRewriteRules(cntx));
rw.clearIngressDstMac(cntx);
assertEquals(true, rw.hasRewriteRules(cntx));
rw.clearEgressSrcMac(cntx);
assertEquals(true, rw.hasRewriteRules(cntx));
rw.clearTtlDecrement(cntx);
assertEquals(false, rw.hasRewriteRules(cntx));
}
@Test
public void testDstMacRulesExceptions() {
try {
rw.setIngressDstMac(1L, 11L, null);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
try {
rw.setIngressDstMac(1L, null, cntx);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
try {
rw.setIngressDstMac(null, 1L, cntx);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
try {
rw.getOrigIngressDstMac(null);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
try {
rw.getFinalIngressDstMac(null);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
try {
rw.clearIngressDstMac(null);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
}
@Test
public void testVlanRulesExceptions() {
try {
rw.setTransportVlan((short)1, null);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
try {
rw.setTransportVlan(null, cntx);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
// check with invalid vlans
Short[] invalidVlans = new Short [] { -1, 0, 4096,
Ethernet.VLAN_UNTAGGED
};
for (Short vlan: invalidVlans) {
try {
rw.setTransportVlan(vlan, cntx);
fail("Expected exception was not thrown");
} catch (IllegalArgumentException e) {
// exptected
}
}
// check with valid vlans. This should succeed
Short[] validVlans = new Short [] { 1, 2, 3,
256, 512, 1024, 2048, 4094, 4095,
42, 424, 23 //, Ethernet.VLAN_UNTAGGED
};
for (Short vlan: validVlans) {
// Set the MAC
rw.setTransportVlan(vlan, cntx);
assertEquals(vlan, rw.getTransportVlan(cntx));
}
try {
rw.getTransportVlan(null);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
try {
rw.clearTransportVlan(null);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
}
@Test
public void testSrcMacRulesExceptions() {
try {
rw.setEgressSrcMac(1L, 11L, null);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
try {
rw.setEgressSrcMac(1L, null, cntx);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
try {
rw.setEgressSrcMac(null, 1L, cntx);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
try {
rw.getOrigEgressSrcMac(null);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
try {
rw.getFinalEgressSrcMac(null);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
try {
rw.clearEgressSrcMac(null);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
}
@Test
public void testTtlDecrementRuleExceptions() {
try {
rw.setTtlDecrement(1, null);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
try {
rw.getTtlDecrement(null);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
try {
rw.clearTtlDecrement(null);
fail("Expected exception was not thrown");
} catch (NullPointerException e) {
// exptected
}
// invalid number of hops
for (int n: new int[] { -1, 0, 255, 256}) {
try {
rw.setTtlDecrement(n, cntx);
fail("Expected exception was not thrown for n=" + n);
} catch (IllegalArgumentException e) {
// exptected
}
}
// valid number of hops
for (int n: new int[] { 1, 2, 3, 42, 253, 254 }) {
rw.setTtlDecrement(n, cntx);
assertEquals(Integer.valueOf(n), rw.getTtlDecrement(cntx));
}
}
@Test
public void testDstMacRules() {
assertNull(rw.getOrigIngressDstMac(cntx));
assertNull(rw.getFinalIngressDstMac(cntx));
rw.clearIngressDstMac(cntx);
assertNull(rw.getOrigIngressDstMac(cntx));
assertNull(rw.getFinalIngressDstMac(cntx));
rw.clearIngressDstMac(cntx);
for (Long origMac: macsToTest) {
for (Long newMac: macsToTest) {
// Set the MAC
rw.setIngressDstMac(origMac, newMac, cntx);
if (origMac.equals(newMac)) {
assertNull(rw.getOrigIngressDstMac(cntx));
assertNull(rw.getFinalIngressDstMac(cntx));
continue;
}
assertEquals(origMac, rw.getOrigIngressDstMac(cntx));
assertEquals(newMac, rw.getFinalIngressDstMac(cntx));
// Make sure there's no effect to the other fields
assertEquals(null, rw.getTransportVlan(cntx));
rw.setTransportVlan((short)1, cntx);
assertEquals(Short.valueOf((short)1), rw.getTransportVlan(cntx));
assertEquals(origMac, rw.getOrigIngressDstMac(cntx));
assertEquals(newMac, rw.getFinalIngressDstMac(cntx));
rw.clearTransportVlan(cntx);
assertEquals(origMac, rw.getOrigIngressDstMac(cntx));
assertEquals(newMac, rw.getFinalIngressDstMac(cntx));
assertNull(rw.getOrigEgressSrcMac(cntx));
assertNull(rw.getFinalEgressSrcMac(cntx));
rw.setEgressSrcMac(1L, 11L, cntx);
assertEquals(Long.valueOf(1L), rw.getOrigEgressSrcMac(cntx));
assertEquals(Long.valueOf(11L), rw.getFinalEgressSrcMac(cntx));
rw.clearEgressSrcMac(cntx);
assertNull(rw.getOrigEgressSrcMac(cntx));
assertNull(rw.getFinalEgressSrcMac(cntx));
// try to reset and clear the MAC
rw.clearIngressDstMac(cntx);
assertNull(rw.getOrigIngressDstMac(cntx));
assertNull(rw.getFinalIngressDstMac(cntx));
}
}
assertNull(rw.getOrigIngressDstMac(cntx));
assertNull(rw.getFinalIngressDstMac(cntx));
assertNull(rw.getTransportVlan(cntx));
}
@Test
public void testSrcMacRules() {
assertNull(rw.getOrigEgressSrcMac(cntx));
assertNull(rw.getFinalEgressSrcMac(cntx));
rw.clearEgressSrcMac(cntx);
assertNull(rw.getOrigEgressSrcMac(cntx));
assertNull(rw.getFinalEgressSrcMac(cntx));
rw.clearEgressSrcMac(cntx);
for (Long origMac: macsToTest) {
for (Long newMac: macsToTest) {
// Set the MAC
rw.setEgressSrcMac(origMac, newMac, cntx);
if (origMac.equals(newMac)) {
assertNull(rw.getOrigEgressSrcMac(cntx));
assertNull(rw.getFinalEgressSrcMac(cntx));
continue;
}
assertEquals(origMac, rw.getOrigEgressSrcMac(cntx));
assertEquals(newMac, rw.getFinalEgressSrcMac(cntx));
// Make sure there's no effect to the other fields
assertEquals(null, rw.getTransportVlan(cntx));
rw.setTransportVlan((short)1, cntx);
assertEquals(Short.valueOf((short)1), rw.getTransportVlan(cntx));
assertEquals(origMac, rw.getOrigEgressSrcMac(cntx));
assertEquals(newMac, rw.getFinalEgressSrcMac(cntx));
assertNull(rw.getOrigIngressDstMac(cntx));
assertNull(rw.getFinalIngressDstMac(cntx));
rw.setIngressDstMac(1L, 11L, cntx);
assertEquals(Long.valueOf(1L), rw.getOrigIngressDstMac(cntx));
assertEquals(Long.valueOf(11L), rw.getFinalIngressDstMac(cntx));
rw.clearIngressDstMac(cntx);
assertNull(rw.getOrigIngressDstMac(cntx));
assertNull(rw.getFinalIngressDstMac(cntx));
rw.clearTransportVlan(cntx);
assertEquals(origMac, rw.getOrigEgressSrcMac(cntx));
assertEquals(newMac, rw.getFinalEgressSrcMac(cntx));
// try to reset and clear the MAC
rw.clearEgressSrcMac(cntx);
assertNull(rw.getOrigEgressSrcMac(cntx));
assertNull(rw.getFinalEgressSrcMac(cntx));
}
}
assertNull(rw.getOrigEgressSrcMac(cntx));
assertNull(rw.getFinalEgressSrcMac(cntx));
assertNull(rw.getTransportVlan(cntx));
}
@Test
public void testVlanRules() {
assertNull(rw.getTransportVlan(cntx));
rw.clearTransportVlan(cntx);
assertNull(rw.getTransportVlan(cntx));
Short[] validVlans = new Short [] { 1, 2, 3,
256, 512, 1024, 2048, 4094, 4095,
42, 424, 23 //, Ethernet.VLAN_UNTAGGED
};
for (Short vlan: validVlans) {
// Set the MAC
rw.setTransportVlan(vlan, cntx);
assertEquals(vlan, rw.getTransportVlan(cntx));
// Make sure there's no effect to the other fields
assertNull(rw.getOrigIngressDstMac(cntx));
assertNull(rw.getFinalIngressDstMac(cntx));
rw.setIngressDstMac(1L, 11L, cntx);
assertEquals(Long.valueOf(1L), rw.getOrigIngressDstMac(cntx));
assertEquals(Long.valueOf(11L), rw.getFinalIngressDstMac(cntx));
assertEquals(vlan, rw.getTransportVlan(cntx));
rw.clearIngressDstMac(cntx);
assertEquals(vlan, rw.getTransportVlan(cntx));
// try to reset and clear the VLAN
rw.setTransportVlan(vlan, cntx);
assertEquals(vlan, rw.getTransportVlan(cntx));
rw.setTransportVlan((short)100, cntx);
assertEquals(Short.valueOf((short)100), rw.getTransportVlan(cntx));
rw.clearTransportVlan(cntx);
assertNull(rw.getTransportVlan(cntx));
}
assertNull(rw.getOrigIngressDstMac(cntx));
assertNull(rw.getFinalIngressDstMac(cntx));
assertNull(rw.getTransportVlan(cntx));
}
@Test
public void testTtlDecrementRules() {
assertNull(rw.getTtlDecrement(cntx));
rw.clearTtlDecrement(cntx);
assertNull(rw.getTtlDecrement(cntx));
int[] validNumHops = new int[] { 1, 2, 3, 4, 42, 254 };
for (int n: validNumHops) {
rw.setTtlDecrement(n, cntx);
// Make sure there's no effect to the other fields
assertNull(rw.getOrigIngressDstMac(cntx));
assertNull(rw.getFinalIngressDstMac(cntx));
rw.setIngressDstMac(1L, 11L, cntx);
assertEquals(Long.valueOf(1L), rw.getOrigIngressDstMac(cntx));
assertEquals(Long.valueOf(11L), rw.getFinalIngressDstMac(cntx));
assertEquals(Integer.valueOf(n), rw.getTtlDecrement(cntx));
rw.clearIngressDstMac(cntx);
assertEquals(Integer.valueOf(n), rw.getTtlDecrement(cntx));
// try to reset and clear the Ttl
rw.setTtlDecrement(n, cntx);
assertEquals(Integer.valueOf(n), rw.getTtlDecrement(cntx));
rw.setTtlDecrement(100, cntx);
assertEquals(Integer.valueOf(100), rw.getTtlDecrement(cntx));
rw.clearTtlDecrement(cntx);
assertNull(rw.getTtlDecrement(cntx));
}
}
@Test
public void testSwitchPortVlanMode() {
SwitchPort swp = new SwitchPort(1L, 1);
Short[] vlans = new Short [] { 1, 2, 3, null,
256, 512, 1024, 2048, 4094, 4095,
42, 424, 23, Ethernet.VLAN_UNTAGGED
};
resetToDefault(addressSpaceManager);
for (Short vlan: vlans) {
String addressSpaceName = "AS" + vlan;
expect(addressSpaceManager.getSwitchPortVlanMode(swp, addressSpaceName,
vlan, true))
.andReturn(vlan).once();
}
replay(addressSpaceManager);
for (Short vlan: vlans) {
String addressSpaceName = "AS" + vlan;
assertEquals(vlan, rw.getSwitchPortVlanMode(swp, addressSpaceName,
vlan, true));
}
verify(addressSpaceManager);
}
}