/* * 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.netvirt.virtualrouting.internal; import org.junit.Before; import org.junit.Test; import org.openflow.protocol.OFMatch; import org.sdnplatform.core.ListenerContext; import org.sdnplatform.core.IControllerService; import org.sdnplatform.core.module.ModuleContext; import org.sdnplatform.core.test.MockThreadPoolService; import org.sdnplatform.core.util.MutableInteger; import org.sdnplatform.devicemanager.IDevice; import org.sdnplatform.devicemanager.IDeviceService; import org.sdnplatform.devicemanager.IEntityClassifierService; import org.sdnplatform.devicemanager.internal.BetterDeviceManagerImpl; import org.sdnplatform.devicemanager.internal.DefaultEntityClassifier; import org.sdnplatform.devicemanager.test.MockDeviceManager; import org.sdnplatform.flowcache.BetterFlowCache; import org.sdnplatform.flowcache.BetterFlowReconcileManager; import org.sdnplatform.flowcache.IFlowCacheService; import org.sdnplatform.flowcache.IFlowReconcileService; import org.sdnplatform.linkdiscovery.ILinkDiscoveryService; import org.sdnplatform.linkdiscovery.internal.LinkDiscoveryManager; import org.sdnplatform.netvirt.core.VNSAccessControlList; import org.sdnplatform.netvirt.core.VNSAccessControlListEntry; import org.sdnplatform.netvirt.manager.INetVirtManagerService; import org.sdnplatform.netvirt.manager.internal.NetVirtManagerImpl; import org.sdnplatform.netvirt.virtualrouting.IVirtualRoutingService; import org.sdnplatform.netvirt.virtualrouting.internal.VirtualRouting; import org.sdnplatform.packet.Data; import org.sdnplatform.packet.Ethernet; import org.sdnplatform.packet.ICMP; import org.sdnplatform.packet.IPacket; import org.sdnplatform.packet.IPv4; import org.sdnplatform.packet.TCP; import org.sdnplatform.packet.UDP; import org.sdnplatform.restserver.IRestApiService; import org.sdnplatform.restserver.RestApiServer; import org.sdnplatform.storage.IStorageSourceService; import org.sdnplatform.storage.memory.MemoryStorageSource; import org.sdnplatform.tagmanager.ITagManagerService; import org.sdnplatform.test.PlatformTestCase; import org.sdnplatform.threadpool.IThreadPoolService; import org.sdnplatform.topology.BetterTopologyManager; import org.sdnplatform.topology.ITopologyService; public class VirtualRoutingHintTest extends PlatformTestCase { protected int defaultHint = OFMatch.OFPFW_ALL & ~(OFMatch.OFPFW_DL_DST | OFMatch.OFPFW_DL_SRC); protected IPacket udpPacket1; protected IPacket tcpPacket1, tcpPacket2; protected IPacket icmpPacket1; protected IPacket arpPacket; private NetVirtManagerImpl netVirtManager; private MockDeviceManager mockDeviceManager; private MemoryStorageSource storageSource; private VirtualRouting virtualRouting; private BetterDeviceManagerImpl betterDeviceManager; private BetterFlowCache betterFlowCacheMgr; private BetterFlowReconcileManager flowRecocileMgr; private LinkDiscoveryManager linkDiscMgr; private BetterTopologyManager topology; private ModuleContext fmc; @Before public void setUp() throws Exception { super.setUp(); storageSource = new MemoryStorageSource(); mockDeviceManager = new MockDeviceManager(); virtualRouting = new VirtualRouting(); betterDeviceManager = new BetterDeviceManagerImpl(); netVirtManager = new NetVirtManagerImpl(); betterFlowCacheMgr = new BetterFlowCache(); flowRecocileMgr = new BetterFlowReconcileManager(); linkDiscMgr = new LinkDiscoveryManager(); topology = new BetterTopologyManager(); RestApiServer ras = new RestApiServer(); MockThreadPoolService tp = new MockThreadPoolService(); DefaultEntityClassifier entityClassifier = new DefaultEntityClassifier(); fmc = new ModuleContext(); fmc.addService(IControllerService.class, mockControllerProvider); fmc.addService(IStorageSourceService.class, storageSource); fmc.addService(IDeviceService.class, mockDeviceManager); fmc.addService(ITagManagerService.class, betterDeviceManager); fmc.addService(IVirtualRoutingService.class, virtualRouting); fmc.addService(INetVirtManagerService.class, netVirtManager); fmc.addService(IFlowCacheService.class, betterFlowCacheMgr); fmc.addService(IFlowReconcileService.class, flowRecocileMgr); fmc.addService(ILinkDiscoveryService.class, linkDiscMgr); fmc.addService(ITopologyService.class, topology); fmc.addService(IRestApiService.class, ras); fmc.addService(IThreadPoolService.class, tp); fmc.addService(IEntityClassifierService.class, entityClassifier); storageSource.init(fmc); mockDeviceManager.init(fmc); betterDeviceManager.init(fmc); virtualRouting.init(fmc); netVirtManager.init(fmc); betterFlowCacheMgr.init(fmc); flowRecocileMgr.init(fmc); linkDiscMgr.init(fmc); topology.init(fmc); ras.init(fmc); mockControllerProvider.init(fmc); tp.init(fmc); entityClassifier.init(fmc); storageSource.startUp(fmc); mockDeviceManager.startUp(fmc); betterDeviceManager.startUp(fmc); virtualRouting.startUp(fmc); netVirtManager.startUp(fmc); betterFlowCacheMgr.startUp(fmc); flowRecocileMgr.startUp(fmc); linkDiscMgr.startUp(fmc); topology.startUp(fmc); ras.startUp(fmc); mockControllerProvider.startUp(fmc); tp.startUp(fmc); entityClassifier.startUp(fmc); buildPackets(); } private void buildPackets() { // Build our test packets this.udpPacket1 = new Ethernet() .setDestinationMACAddress("00:00:00:00:00:02") .setSourceMACAddress("00:00:00:00:00:01") .setVlanID((short) 42) .setEtherType(Ethernet.TYPE_IPv4) .setPayload( new IPv4() .setTtl((byte) 128) .setSourceAddress("192.168.1.1") .setDestinationAddress("192.168.1.2") .setProtocol(IPv4.PROTOCOL_UDP) .setPayload(new UDP() .setSourcePort((short) 5000) .setDestinationPort((short) 5001) .setPayload(new Data(new byte[] {0x01})))); this.tcpPacket1 = new Ethernet() .setDestinationMACAddress("00:00:00:00:00:02") .setSourceMACAddress("00:00:00:00:00:01") .setVlanID((short) 42) .setEtherType(Ethernet.TYPE_IPv4) .setPayload( new IPv4() .setTtl((byte) 128) .setSourceAddress("192.168.1.1") .setDestinationAddress("192.168.1.2") .setProtocol(IPv4.PROTOCOL_TCP) .setPayload(new TCP() .setSourcePort((short) 5000) .setDestinationPort((short) 5001) .setPayload(new Data(new byte[] {0x01})))); this.tcpPacket2 = new Ethernet() .setDestinationMACAddress("00:00:00:00:00:03") .setSourceMACAddress("00:00:00:00:00:01") .setVlanID((short) 42) .setEtherType(Ethernet.TYPE_IPv4) .setPayload( new IPv4() .setTtl((byte) 128) .setSourceAddress("192.168.1.1") .setDestinationAddress("192.168.1.3") .setProtocol(IPv4.PROTOCOL_TCP) .setPayload(new TCP() .setSourcePort((short) 33000) .setDestinationPort((short) 5001))); this.icmpPacket1 = new Ethernet() .setDestinationMACAddress("00:00:00:00:00:03") .setSourceMACAddress("00:00:00:00:00:01") .setVlanID((short) 42) .setEtherType(Ethernet.TYPE_IPv4) .setPayload( new IPv4() .setTtl((byte) 128) .setSourceAddress("192.168.1.1") .setDestinationAddress("192.168.1.3") .setProtocol(IPv4.PROTOCOL_ICMP) .setPayload(new ICMP() .setIcmpType((byte) 8) .setPayload(new Data(new byte[] {1, 2, 3})))); // Not a read ARP packet, just need the mac header for testing this.arpPacket = new Ethernet() .setDestinationMACAddress("00:00:00:00:00:03") .setSourceMACAddress("00:00:00:00:00:01") .setEtherType(Ethernet.TYPE_ARP) .setPad(true); } /** * Apply acl and verify hint is as expected */ private void testHintInternal (VNSAccessControlList acl, Ethernet eth, int expectedWildcards) { MutableInteger hint = new MutableInteger(defaultHint); ListenerContext cntx = new ListenerContext(); IDevice srcDev = null, dstDev = null; Integer srcIpAddr = null, dstIpAddr = null; if (eth.getEtherType() == Ethernet.TYPE_IPv4) { srcIpAddr = ((IPv4) eth.getPayload()).getSourceAddress(); dstIpAddr = ((IPv4) eth.getPayload()).getDestinationAddress(); } /* * Learn source and destination entity devices, as they are required * during match rules execution in acls. */ srcDev = mockDeviceManager.learnEntity( Ethernet.toLong(eth.getSourceMACAddress()), null, srcIpAddr, 1L, 1); dstDev = mockDeviceManager.learnEntity( Ethernet.toLong(eth.getDestinationMACAddress()), null, dstIpAddr, 1L, 1); IControllerService.bcStore. put(cntx, IControllerService.CONTEXT_PI_PAYLOAD, eth); if (srcDev != null) { IDeviceService.fcStore.put(cntx, IDeviceService.CONTEXT_SRC_DEVICE, srcDev); } if (dstDev != null) { IDeviceService.fcStore.put(cntx, IDeviceService.CONTEXT_DST_DEVICE, dstDev); } // No context and direction for test case acl.applyAcl(eth, hint, cntx, null); assertTrue(hint.intValue() == expectedWildcards); } /** * Return a mac acl entry */ private VNSAccessControlListEntry macAclEntry(int etherType, int vlan) throws Exception { VNSAccessControlListEntry aclMac = new VNSAccessControlListEntry(10, null); aclMac.setAction("permit"); aclMac.setType("mac"); aclMac.setSrcMac(null); aclMac.setDstMac(null); aclMac.setEtherType(etherType); aclMac.setVlan(vlan); return aclMac; } /** * Mac ACL with no etherType or VLAN should have default hint */ @Test public void testMacDefault() throws Exception { VNSAccessControlList acl = new VNSAccessControlList("testAcl"); VNSAccessControlListEntry macAcl = macAclEntry( VNSAccessControlListEntry.ETHERTYPE_ALL, VNSAccessControlListEntry.VLAN_ALL); acl.addAclEntry(macAcl); testHintInternal(acl, (Ethernet) udpPacket1, defaultHint); } /** * Mac ACL with no VLAN should have default hint minus vlan wildcard */ @Test public void testMacVlan() throws Exception { VNSAccessControlList acl = new VNSAccessControlList("testAcl"); VNSAccessControlListEntry macAcl = macAclEntry( VNSAccessControlListEntry.ETHERTYPE_ALL, 42); acl.addAclEntry(macAcl); testHintInternal(acl, (Ethernet) udpPacket1, defaultHint & ~OFMatch.OFPFW_DL_VLAN); } /** * Mac ACL with etherType or VLAN shouldn't wildcard vlan or DL_TYPE */ @Test public void testMacVlanEthType() throws Exception { VNSAccessControlList acl = new VNSAccessControlList("testAcl"); VNSAccessControlListEntry macAcl = macAclEntry(0x800, 42); acl.addAclEntry(macAcl); testHintInternal(acl, (Ethernet) udpPacket1, defaultHint & ~(OFMatch.OFPFW_DL_VLAN | OFMatch.OFPFW_DL_TYPE)); } /** * Return a mac acl entry */ private VNSAccessControlListEntry ipprotoAclEntry(int seqNo, int ipproto, String srcIpMask, String dstIpMask) throws Exception { VNSAccessControlListEntry aclIp = new VNSAccessControlListEntry(seqNo, null); aclIp.setAction("permit"); if (ipproto == VNSAccessControlListEntry.IPPROTO_ALL) { aclIp.setType("ip"); } else { aclIp.setType(Integer.toString(ipproto)); } aclIp.setSrcIp("192.168.1.64"); aclIp.setSrcIpMask(srcIpMask); aclIp.setDstIp("192.168.1.64"); aclIp.setDstIpMask(dstIpMask); return aclIp; } /** * Test IP ACL with dst mask */ @Test public void testIpDst() throws Exception { VNSAccessControlList acl = new VNSAccessControlList("testAcl"); VNSAccessControlListEntry ipAcl = ipprotoAclEntry(20, VNSAccessControlListEntry.IPPROTO_ALL, "255.255.255.255", "0.0.0.255"); acl.addAclEntry(ipAcl); testHintInternal(acl, (Ethernet) udpPacket1, (defaultHint & ~(OFMatch.OFPFW_DL_TYPE | OFMatch.OFPFW_NW_DST_MASK)) | (8 << OFMatch.OFPFW_NW_DST_SHIFT)); } /** * Test ipproto ACL with src mask */ @Test public void testIpproto() throws Exception { VNSAccessControlList acl = new VNSAccessControlList("testAcl"); VNSAccessControlListEntry ipprotoAcl = ipprotoAclEntry(20, 1, "1.0.0.255", "255.255.255.255"); acl.addAclEntry(ipprotoAcl); testHintInternal(acl, (Ethernet) icmpPacket1, (defaultHint & ~(OFMatch.OFPFW_DL_TYPE | OFMatch.OFPFW_NW_PROTO | OFMatch.OFPFW_NW_SRC_MASK)) | (8 << OFMatch.OFPFW_NW_SRC_SHIFT)); } /** * Create icmp ACL entry */ private VNSAccessControlListEntry icmpAclEntry(int icmpType) throws Exception { VNSAccessControlListEntry aclIcmp = new VNSAccessControlListEntry(30, null); aclIcmp.setAction("deny"); aclIcmp.setType("icmp"); aclIcmp.setSrcIp("192.168.1.64"); aclIcmp.setSrcIpMask("255.255.255.255"); aclIcmp.setDstIp("192.168.1.64"); aclIcmp.setDstIpMask("255.255.255.255"); aclIcmp.setIcmpType(icmpType); return aclIcmp; } /** * Test icmp ACL with no ICMP type matching */ @Test public void testIcmpAllType() throws Exception { VNSAccessControlList acl = new VNSAccessControlList("testAcl"); VNSAccessControlListEntry icmpAcl = icmpAclEntry(VNSAccessControlListEntry.ICMPTYPE_ALL); acl.addAclEntry(icmpAcl); testHintInternal(acl, (Ethernet) icmpPacket1, defaultHint & ~(OFMatch.OFPFW_DL_TYPE | OFMatch.OFPFW_NW_PROTO)); } /** * Test icmp ACL with ICMP type matching */ @Test public void testIcmpWithType() throws Exception { VNSAccessControlList acl = new VNSAccessControlList("testAcl"); VNSAccessControlListEntry icmpAcl = icmpAclEntry(8); acl.addAclEntry(icmpAcl); testHintInternal(acl, (Ethernet) icmpPacket1, defaultHint & ~(OFMatch.OFPFW_DL_TYPE | OFMatch.OFPFW_NW_PROTO | OFMatch.OFPFW_TP_SRC)); } /** * Create tcp/udp ACL entry */ private VNSAccessControlListEntry tpAclEntry(int seqNo, String type, String tpSrcOp, String tpDstOp) throws Exception { VNSAccessControlListEntry aclTp = new VNSAccessControlListEntry(seqNo, null); aclTp.setAction("deny"); aclTp.setType(type); aclTp.setSrcIp("192.168.1.64"); aclTp.setSrcIpMask("255.255.255.255"); aclTp.setDstIp("192.168.1.64"); aclTp.setDstIpMask("255.255.255.255"); aclTp.setSrcTpPortOp(tpSrcOp); aclTp.setSrcTpPort(5000); aclTp.setDstTpPortOp(tpDstOp); aclTp.setDstTpPort(5001); return aclTp; } /** * Test tcp ACL with specific destination port */ @Test public void testTcpDstPort() throws Exception { VNSAccessControlList acl = new VNSAccessControlList("testAcl"); VNSAccessControlListEntry tcpAcl = tpAclEntry(40, "tcp", "any", "eq"); acl.addAclEntry(tcpAcl); testHintInternal(acl, (Ethernet) tcpPacket1, defaultHint & ~(OFMatch.OFPFW_DL_TYPE | OFMatch.OFPFW_NW_PROTO | OFMatch.OFPFW_TP_DST)); } /** * Test udp ACL with specific src/dst port */ @Test public void testUdpWithPorts() throws Exception { VNSAccessControlList acl = new VNSAccessControlList("testAcl"); VNSAccessControlListEntry udpAcl = tpAclEntry(40, "udp", "eq", "eq"); acl.addAclEntry(udpAcl); testHintInternal(acl, (Ethernet) udpPacket1, defaultHint & ~(OFMatch.OFPFW_DL_TYPE | OFMatch.OFPFW_NW_PROTO | OFMatch.OFPFW_TP_DST | OFMatch.OFPFW_TP_SRC)); } /** * Test mixed ACL entry types */ @Test public void testMixedAclTypes() throws Exception { VNSAccessControlList acl = new VNSAccessControlList("testAcl"); acl.addAclEntry(macAclEntry(Ethernet.TYPE_ARP, VNSAccessControlListEntry.VLAN_ALL)); acl.addAclEntry(ipprotoAclEntry(20, 25, "0.0.0.0", "0.0.0.0")); acl.addAclEntry(ipprotoAclEntry(25, VNSAccessControlListEntry.IPPROTO_ALL, "0.3.0.63", "0.0.0.15")); acl.addAclEntry(icmpAclEntry(8)); acl.addAclEntry(tpAclEntry(50, "tcp", "neq", "any")); acl.addAclEntry(tpAclEntry(60, "udp", "eq", "eq")); // match mac entry testHintInternal(acl, (Ethernet) arpPacket, defaultHint & ~(OFMatch.OFPFW_DL_TYPE)); // match icmp entry testHintInternal(acl, (Ethernet) icmpPacket1, (defaultHint & ~(OFMatch.OFPFW_DL_TYPE | OFMatch.OFPFW_NW_PROTO | OFMatch.OFPFW_NW_SRC_MASK | OFMatch.OFPFW_TP_SRC)) | (6 << OFMatch.OFPFW_NW_SRC_SHIFT)); // match tcp entry testHintInternal(acl, (Ethernet) tcpPacket2, (defaultHint & ~(OFMatch.OFPFW_DL_TYPE | OFMatch.OFPFW_NW_PROTO | OFMatch.OFPFW_NW_SRC_MASK | OFMatch.OFPFW_TP_SRC)) | (6 << OFMatch.OFPFW_NW_SRC_SHIFT)); // match udp entry testHintInternal(acl, (Ethernet) udpPacket1, (defaultHint & ~(OFMatch.OFPFW_DL_TYPE | OFMatch.OFPFW_NW_PROTO | OFMatch.OFPFW_NW_SRC_MASK | OFMatch.OFPFW_TP_SRC | OFMatch.OFPFW_TP_DST)) | (6 << OFMatch.OFPFW_NW_SRC_SHIFT)); } }