/* * 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 static org.easymock.EasyMock.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Before; import org.junit.Test; import org.openflow.protocol.OFPacketIn; import org.openflow.protocol.OFPacketIn.OFPacketInReason; import org.sdnplatform.core.ListenerContext; import org.sdnplatform.core.IControllerService; import org.sdnplatform.core.IOFSwitch; import org.sdnplatform.core.module.ModuleContext; import org.sdnplatform.core.test.MockThreadPoolService; import org.sdnplatform.devicemanager.IDevice; import org.sdnplatform.devicemanager.IDeviceService; import org.sdnplatform.devicemanager.IEntityClassifierService; import org.sdnplatform.devicemanager.SwitchPort; import org.sdnplatform.devicemanager.internal.DefaultEntityClassifier; import org.sdnplatform.devicemanager.test.MockDeviceManager; import org.sdnplatform.flowcache.IFlowCacheService; import org.sdnplatform.flowcache.IFlowReconcileListener; import org.sdnplatform.flowcache.IFlowReconcileService; import org.sdnplatform.netvirt.core.VNS; import org.sdnplatform.netvirt.core.VNSAccessControlListEntry; import org.sdnplatform.netvirt.core.NetVirtExplainPacket; import org.sdnplatform.netvirt.core.VNSInterface; import org.sdnplatform.netvirt.manager.INetVirtManagerService; 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.routing.IRoutingDecision; import org.sdnplatform.routing.IRoutingDecision.RoutingAction; import org.sdnplatform.storage.IResultSet; import org.sdnplatform.storage.IStorageSourceService; import org.sdnplatform.storage.memory.MemoryStorageSource; import org.sdnplatform.test.PlatformTestCase; import org.sdnplatform.threadpool.IThreadPoolService; import org.sdnplatform.topology.ITopologyService; import org.sdnplatform.tunnelmanager.ITunnelManagerService; @SuppressWarnings("unchecked") public class VirtualRoutingAclTest extends PlatformTestCase { private INetVirtManagerService netVirtManager; private MockDeviceManager mockDeviceManager; private MemoryStorageSource storageSource; private VirtualRouting virtualRouting; private IFlowCacheService betterFlowCacheMgr; private IFlowReconcileService flowRecocileMgr; private ITopologyService topology; private ModuleContext fmc; private ITunnelManagerService tunnelManager; protected class AclTest { ArrayList<Map<String, Object>> aclList = new ArrayList<Map<String, Object>>(); ArrayList<Map<String, Object>> aclEntryList = new ArrayList<Map<String, Object>>(); ArrayList<Map<String, Object>> ifAclList = new ArrayList<Map<String, Object>>(); public void addAcl(Map<String, Object>... acls) { for (Map<String, Object> acl : acls) { aclList.add(acl); } } public void addAclEntry(Map<String, Object>... entries) { for (Map<String, Object> entry : entries) { aclEntryList.add(entry); } } public void addIfAcl(Map<String, Object>... ifacls) { for (Map<String, Object> ifacl : ifacls) { ifAclList.add(ifacl); } } public void writeToStorage(IStorageSourceService storageSource) { for (Map<String, Object> row : aclList) { storageSource.insertRow(VirtualRouting.VNS_ACL_TABLE_NAME, row); } for (Map<String, Object> row : aclEntryList) { storageSource.insertRow(VirtualRouting.VNS_ACL_ENTRY_TABLE_NAME, row); } for (Map<String, Object> row : ifAclList) { storageSource.insertRow(VirtualRouting.VNS_INTERFACE_ACL_TABLE_NAME, row); } } } private static void clearStorage(IStorageSourceService storageSource) { IResultSet rSet = storageSource.executeQuery(VirtualRouting.VNS_ACL_TABLE_NAME, new String[]{VirtualRouting.ID_COLUMN_NAME}, null, null); while (rSet.next()) { String id = rSet.getString(VirtualRouting.ID_COLUMN_NAME); storageSource.deleteRow(VirtualRouting.VNS_ACL_TABLE_NAME, id); } rSet = storageSource.executeQuery(VirtualRouting.VNS_ACL_ENTRY_TABLE_NAME, new String[]{VirtualRouting.ID_COLUMN_NAME}, null, null); while (rSet.next()) { String id = rSet.getString(VirtualRouting.ID_COLUMN_NAME); storageSource.deleteRow(VirtualRouting.VNS_ACL_ENTRY_TABLE_NAME, id); } rSet = storageSource.executeQuery(VirtualRouting.VNS_INTERFACE_ACL_TABLE_NAME, new String[]{VirtualRouting.ID_COLUMN_NAME}, null, null); while (rSet.next()) { String id = rSet.getString(VirtualRouting.ID_COLUMN_NAME); storageSource.deleteRow(VirtualRouting.VNS_INTERFACE_ACL_TABLE_NAME, id); } } private static final Map<String, Object> acl1; static { // for ip, ipproto, icmp tests acl1 = new HashMap<String, Object>(); acl1.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl1"); acl1.put(VirtualRouting.NAME_COLUMN_NAME, "acl1"); acl1.put(VirtualRouting.PRIORITY_COLUMN_NAME, 1000); } private static final Map<String, Object> acl2; static { // for priority test, override acl1 via if1/if2 acl2 = new HashMap<String, Object>(); acl2.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl2"); acl2.put(VirtualRouting.NAME_COLUMN_NAME, "acl2"); acl2.put(VirtualRouting.PRIORITY_COLUMN_NAME, 2000); } private static final Map<String, Object> acl3; static { // test default deny of empty acl acl3 = new HashMap<String, Object>(); acl3.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl3"); acl3.put(VirtualRouting.NAME_COLUMN_NAME, "acl3"); acl3.put(VirtualRouting.PRIORITY_COLUMN_NAME, 3000); } private static final Map<String, Object> acl4; static { // test udp/tcp rules acl4 = new HashMap<String, Object>(); acl4.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl4"); acl4.put(VirtualRouting.NAME_COLUMN_NAME, "acl4"); acl4.put(VirtualRouting.PRIORITY_COLUMN_NAME, 4000); } private static final Map<String, Object> acl5; static { // test mac rules acl5 = new HashMap<String, Object>(); acl5.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl5"); acl5.put(VirtualRouting.NAME_COLUMN_NAME, "acl5"); acl5.put(VirtualRouting.PRIORITY_COLUMN_NAME, 4000); } private static final Map<String, Object> entry1_1; static { // ip: deny 192.168.1.1->.2 entry1_1 = new HashMap<String, Object>(); entry1_1.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl1|210"); entry1_1.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl1"); entry1_1.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "210"); entry1_1.put(VirtualRouting.TYPE_COLUMN_NAME, "ip"); entry1_1.put(VirtualRouting.ACTION_COLUMN_NAME, "deny"); entry1_1.put(VirtualRouting.SRC_IP_COLUMN_NAME, "192.168.1.1"); entry1_1.put(VirtualRouting.SRC_IP_MASK_COLUMN_NAME, "0.0.0.0"); entry1_1.put(VirtualRouting.DST_IP_COLUMN_NAME, "192.168.1.2"); entry1_1.put(VirtualRouting.DST_IP_MASK_COLUMN_NAME, "0.0.0.0"); } private static final Map<String, Object> entry1_2; static { // ip: deny 192.168.1.2->.1 entry1_2 = new HashMap<String, Object>(); entry1_2.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl1|220"); entry1_2.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl1"); entry1_2.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "220"); entry1_2.put(VirtualRouting.TYPE_COLUMN_NAME, "ip"); entry1_2.put(VirtualRouting.ACTION_COLUMN_NAME, "deny"); entry1_2.put(VirtualRouting.SRC_IP_COLUMN_NAME, "192.168.1.2"); entry1_2.put(VirtualRouting.SRC_IP_MASK_COLUMN_NAME, "0.0.0.0"); entry1_2.put(VirtualRouting.DST_IP_COLUMN_NAME, "192.168.1.1"); entry1_2.put(VirtualRouting.DST_IP_MASK_COLUMN_NAME, "0.0.0.0"); } private static final Map<String, Object> entry1_3; static { // ip: permit 192.168.1.0/24 subnet entry1_3 = new HashMap<String, Object>(); entry1_3.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl1|230"); entry1_3.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl1"); entry1_3.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "230"); entry1_3.put(VirtualRouting.TYPE_COLUMN_NAME, "ip"); entry1_3.put(VirtualRouting.ACTION_COLUMN_NAME, "permit"); entry1_3.put(VirtualRouting.SRC_IP_COLUMN_NAME, "192.168.1.2"); entry1_3.put(VirtualRouting.SRC_IP_MASK_COLUMN_NAME, "0.0.0.255"); entry1_3.put(VirtualRouting.DST_IP_COLUMN_NAME, "192.168.1.1"); entry1_3.put(VirtualRouting.DST_IP_MASK_COLUMN_NAME, "0.0.0.255"); } private static final Map<String, Object> entry1_4; static { // ipproto: deny protocol 13 (ARGUS) entry1_4 = new HashMap<String, Object>(); entry1_4.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl1|110"); entry1_4.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl1"); entry1_4.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "110"); entry1_4.put(VirtualRouting.TYPE_COLUMN_NAME, "13"); // some random protocol entry1_4.put(VirtualRouting.ACTION_COLUMN_NAME, "deny"); entry1_4.put(VirtualRouting.SRC_IP_COLUMN_NAME, "192.168.1.1"); entry1_4.put(VirtualRouting.SRC_IP_MASK_COLUMN_NAME, "0.0.0.0"); entry1_4.put(VirtualRouting.DST_IP_COLUMN_NAME, "192.168.1.3"); entry1_4.put(VirtualRouting.DST_IP_MASK_COLUMN_NAME, "0.0.0.0"); } private static final Map<String, Object> entry1_5; static { // icmp: deny type 8 entry1_5 = new HashMap<String, Object>(); entry1_5.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl1|120"); entry1_5.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl1"); entry1_5.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "120"); entry1_5.put(VirtualRouting.TYPE_COLUMN_NAME, "icmp"); entry1_5.put(VirtualRouting.ACTION_COLUMN_NAME, "deny"); entry1_5.put(VirtualRouting.SRC_IP_COLUMN_NAME, "192.168.1.1"); entry1_5.put(VirtualRouting.SRC_IP_MASK_COLUMN_NAME, "0.0.0.0"); entry1_5.put(VirtualRouting.DST_IP_COLUMN_NAME, "192.168.1.3"); entry1_5.put(VirtualRouting.DST_IP_MASK_COLUMN_NAME, "0.0.0.0"); entry1_5.put(VirtualRouting.ICMP_TYPE_COLUMN_NAME, 8); } private static final Map<String, Object> entry2_1; static { // ip: deny traffic within subnet 192.168.1.0/24 entry2_1 = new HashMap<String, Object>(); entry2_1.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl2|20"); entry2_1.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl2"); entry2_1.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "20"); entry2_1.put(VirtualRouting.TYPE_COLUMN_NAME, "ip"); entry2_1.put(VirtualRouting.ACTION_COLUMN_NAME, "deny"); entry2_1.put(VirtualRouting.SRC_IP_COLUMN_NAME, "192.168.1.2"); entry2_1.put(VirtualRouting.SRC_IP_MASK_COLUMN_NAME, "0.0.0.255"); entry2_1.put(VirtualRouting.DST_IP_COLUMN_NAME, "192.168.1.1"); entry2_1.put(VirtualRouting.DST_IP_MASK_COLUMN_NAME, "0.0.0.255"); } private static final Map<String, Object> entry2_2; static { // ip: deny traffic within subnet 192.168.1.0/24 entry2_2 = new HashMap<String, Object>(); entry2_2.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl2|120"); entry2_2.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl2"); entry2_2.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "120"); entry2_2.put(VirtualRouting.TYPE_COLUMN_NAME, "ip"); entry2_2.put(VirtualRouting.ACTION_COLUMN_NAME, "permit"); } private static final Map<String, Object> entry4_1; static { // udp: deny 5000->5001 entry4_1 = new HashMap<String, Object>(); entry4_1.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl4|120"); entry4_1.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl4"); entry4_1.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "120"); entry4_1.put(VirtualRouting.TYPE_COLUMN_NAME, "udp"); entry4_1.put(VirtualRouting.ACTION_COLUMN_NAME, "deny"); entry4_1.put(VirtualRouting.SRC_IP_COLUMN_NAME, "192.168.1.0"); entry4_1.put(VirtualRouting.SRC_IP_MASK_COLUMN_NAME, "0.0.0.255"); entry4_1.put(VirtualRouting.DST_IP_COLUMN_NAME, "192.168.1.0"); entry4_1.put(VirtualRouting.DST_IP_MASK_COLUMN_NAME, "0.0.0.255"); entry4_1.put(VirtualRouting.SRC_TP_PORT_OP_COLUMN_NAME, "eq"); entry4_1.put(VirtualRouting.SRC_TP_PORT_COLUMN_NAME, 5000); entry4_1.put(VirtualRouting.DST_TP_PORT_OP_COLUMN_NAME, "eq"); entry4_1.put(VirtualRouting.DST_TP_PORT_COLUMN_NAME, 5001); } private static final Map<String, Object> entry4_2; static { // tcp: deny all except 5000->5001 entry4_2 = new HashMap<String, Object>(); entry4_2.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl4|150"); entry4_2.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl4"); entry4_2.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "150"); entry4_2.put(VirtualRouting.TYPE_COLUMN_NAME, "tcp"); entry4_2.put(VirtualRouting.ACTION_COLUMN_NAME, "deny"); entry4_2.put(VirtualRouting.SRC_IP_COLUMN_NAME, "192.168.1.0"); entry4_2.put(VirtualRouting.SRC_IP_MASK_COLUMN_NAME, "0.0.0.255"); entry4_2.put(VirtualRouting.DST_IP_COLUMN_NAME, "192.168.1.0"); entry4_2.put(VirtualRouting.DST_IP_MASK_COLUMN_NAME, "0.0.0.255"); entry4_2.put(VirtualRouting.SRC_TP_PORT_OP_COLUMN_NAME, "neq"); entry4_2.put(VirtualRouting.SRC_TP_PORT_COLUMN_NAME, 5000); entry4_2.put(VirtualRouting.DST_TP_PORT_OP_COLUMN_NAME, "neq"); entry4_2.put(VirtualRouting.DST_TP_PORT_COLUMN_NAME, 5001); } private static final Map<String, Object> entry4_3; static { // udp: permit any->any entry4_3 = new HashMap<String, Object>(); entry4_3.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl4|220"); entry4_3.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl4"); entry4_3.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "220"); entry4_3.put(VirtualRouting.TYPE_COLUMN_NAME, "udp"); entry4_3.put(VirtualRouting.ACTION_COLUMN_NAME, "permit"); entry4_3.put(VirtualRouting.SRC_IP_COLUMN_NAME, "192.168.1.0"); entry4_3.put(VirtualRouting.SRC_IP_MASK_COLUMN_NAME, "0.0.0.255"); entry4_3.put(VirtualRouting.DST_IP_COLUMN_NAME, "192.168.1.0"); entry4_3.put(VirtualRouting.DST_IP_MASK_COLUMN_NAME, "0.0.0.255"); entry4_3.put(VirtualRouting.SRC_TP_PORT_OP_COLUMN_NAME, "any"); entry4_3.put(VirtualRouting.DST_TP_PORT_OP_COLUMN_NAME, "any"); } private static final Map<String, Object> entry4_4; static { // tcp: permit any->any entry4_4 = new HashMap<String, Object>(); entry4_4.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl4|250"); entry4_4.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl4"); entry4_4.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "250"); entry4_4.put(VirtualRouting.TYPE_COLUMN_NAME, "tcp"); entry4_4.put(VirtualRouting.ACTION_COLUMN_NAME, "permit"); entry4_4.put(VirtualRouting.SRC_IP_COLUMN_NAME, "192.168.1.0"); entry4_4.put(VirtualRouting.SRC_IP_MASK_COLUMN_NAME, "0.0.0.255"); entry4_4.put(VirtualRouting.DST_IP_COLUMN_NAME, "192.168.1.0"); entry4_4.put(VirtualRouting.DST_IP_MASK_COLUMN_NAME, "0.0.0.255"); entry4_4.put(VirtualRouting.SRC_TP_PORT_OP_COLUMN_NAME, "any"); entry4_4.put(VirtualRouting.DST_TP_PORT_OP_COLUMN_NAME, "any"); } private static final Map<String, Object> entry5_1; static { // mac: permit ARP :01->:03 entry5_1 = new HashMap<String, Object>(); entry5_1.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl5|20"); entry5_1.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl5"); entry5_1.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "20"); entry5_1.put(VirtualRouting.TYPE_COLUMN_NAME, "mac"); entry5_1.put(VirtualRouting.ACTION_COLUMN_NAME, "deny"); entry5_1.put(VirtualRouting.SRC_MAC_COLUMN_NAME, "00:00:00:00:00:01"); entry5_1.put(VirtualRouting.DST_MAC_COLUMN_NAME, "00:00:00:00:00:03"); entry5_1.put(VirtualRouting.ETHER_TYPE_COLUMN_NAME, Ethernet.TYPE_ARP); } private static final Map<String, Object> entry5_2; static { // mac: deny IP any->:03 entry5_2 = new HashMap<String, Object>(); entry5_2.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl5|40"); entry5_2.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl5"); entry5_2.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "40"); entry5_2.put(VirtualRouting.TYPE_COLUMN_NAME, "mac"); entry5_2.put(VirtualRouting.ACTION_COLUMN_NAME, "deny"); entry5_2.put(VirtualRouting.DST_MAC_COLUMN_NAME, "00:00:00:00:00:03"); entry5_2.put(VirtualRouting.ETHER_TYPE_COLUMN_NAME, Ethernet.TYPE_IPv4); } private static final Map<String, Object> entry5_3; static { // mac: permit all entry5_3 = new HashMap<String, Object>(); entry5_3.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl5|520"); entry5_3.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl5"); entry5_3.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "520"); entry5_3.put(VirtualRouting.TYPE_COLUMN_NAME, "mac"); entry5_3.put(VirtualRouting.ACTION_COLUMN_NAME, "permit"); entry5_3.put(VirtualRouting.ETHER_TYPE_COLUMN_NAME, 0x10000); } private static final Map<String, Object> entry5_4; static { // mac: deny broadcast from :01 entry5_4 = new HashMap<String, Object>(); entry5_4.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl5|200"); entry5_4.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl5"); entry5_4.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "200"); entry5_4.put(VirtualRouting.TYPE_COLUMN_NAME, "mac"); entry5_4.put(VirtualRouting.ACTION_COLUMN_NAME, "permit"); entry5_4.put(VirtualRouting.SRC_MAC_COLUMN_NAME, "00:00:00:00:00:01"); entry5_4.put(VirtualRouting.DST_MAC_COLUMN_NAME, "ff:ff:ff:ff:ff:ff"); } private static final Map<String, Object> entry5_5; static { // mac: permit broadcast from :03 entry5_5 = new HashMap<String, Object>(); entry5_5.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|acl5|210"); entry5_5.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|acl5"); entry5_5.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "210"); entry5_5.put(VirtualRouting.TYPE_COLUMN_NAME, "mac"); entry5_5.put(VirtualRouting.ACTION_COLUMN_NAME, "deny"); entry5_5.put(VirtualRouting.SRC_MAC_COLUMN_NAME, "00:00:00:00:00:03"); entry5_5.put(VirtualRouting.DST_MAC_COLUMN_NAME, "ff:ff:ff:ff:ff:ff"); } // NetVirtInterfae to ACL associations private static final Map<String, Object> ifAcl1in; static { ifAcl1in = new HashMap<String, Object>(); ifAcl1in.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|if1|netVirt|acl1|in"); ifAcl1in.put(VirtualRouting.INTERFACE_COLUMN_NAME, "netVirt|if1"); ifAcl1in.put(VirtualRouting.ACL_NAME_COLUMN_NAME, "netVirt|acl1"); ifAcl1in.put(VirtualRouting.IN_OUT_COLUMN_NAME, "in"); ifAcl1in.put(VirtualRouting.PRIORITY_COLUMN_NAME, 100); } private static final Map<String, Object> ifAcl1out; static { ifAcl1out = new HashMap<String, Object>(); ifAcl1out.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|if1|netVirt|acl1|out"); ifAcl1out.put(VirtualRouting.INTERFACE_COLUMN_NAME, "netVirt|if1"); ifAcl1out.put(VirtualRouting.ACL_NAME_COLUMN_NAME, "netVirt|acl1"); ifAcl1out.put(VirtualRouting.IN_OUT_COLUMN_NAME, "out"); } private static final Map<String, Object> ifAcl2in; static { ifAcl2in = new HashMap<String, Object>(); ifAcl2in.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|if2|netVirt|acl2|in"); ifAcl2in.put(VirtualRouting.INTERFACE_COLUMN_NAME, "netVirt|if2"); ifAcl2in.put(VirtualRouting.ACL_NAME_COLUMN_NAME, "netVirt|acl2"); ifAcl2in.put(VirtualRouting.IN_OUT_COLUMN_NAME, "in"); } private static final Map<String, Object> ifAcl2out; static { ifAcl2out = new HashMap<String, Object>(); ifAcl2out.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|if2|netVirt|acl2|out"); ifAcl2out.put(VirtualRouting.INTERFACE_COLUMN_NAME, "netVirt|if2"); ifAcl2out.put(VirtualRouting.ACL_NAME_COLUMN_NAME, "netVirt|acl2"); ifAcl2out.put(VirtualRouting.IN_OUT_COLUMN_NAME, "out"); } private static final Map<String, Object> ifAcl3out; static { ifAcl3out = new HashMap<String, Object>(); ifAcl3out.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|if3|netVirt|acl3|out"); ifAcl3out.put(VirtualRouting.INTERFACE_COLUMN_NAME, "netVirt|if3"); ifAcl3out.put(VirtualRouting.ACL_NAME_COLUMN_NAME, "netVirt|acl3"); ifAcl3out.put(VirtualRouting.IN_OUT_COLUMN_NAME, "out"); } private static final Map<String, Object> ifAcl4in; static { ifAcl4in = new HashMap<String, Object>(); ifAcl4in.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|if4|netVirt|acl4|in"); ifAcl4in.put(VirtualRouting.INTERFACE_COLUMN_NAME, "netVirt|if4"); ifAcl4in.put(VirtualRouting.ACL_NAME_COLUMN_NAME, "netVirt|acl4"); ifAcl4in.put(VirtualRouting.IN_OUT_COLUMN_NAME, "in"); } private static final Map<String, Object> ifAcl5in; static { ifAcl5in = new HashMap<String, Object>(); ifAcl5in.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|if5|netVirt|acl5|in"); ifAcl5in.put(VirtualRouting.INTERFACE_COLUMN_NAME, "netVirt|if5"); ifAcl5in.put(VirtualRouting.ACL_NAME_COLUMN_NAME, "netVirt|acl5"); ifAcl5in.put(VirtualRouting.IN_OUT_COLUMN_NAME, "in"); } // NetVirt interfaces private static final VNS netVirt = new VNS("netVirt"); private static final VNSInterface if2 = new VNSInterface("if2", netVirt, null, null);; private static final VNSInterface if1 = new VNSInterface("if1", netVirt, null, if2); private static final VNSInterface if3 = new VNSInterface("if3", netVirt, null, null); private static final VNSInterface if4 = new VNSInterface("if4", netVirt, null, if2); private static final VNSInterface if5 = new VNSInterface("if5", netVirt, null, null); protected IPacket udpPacket1, udpPacket2, udpPacket3; protected byte[] udpPacketSerialized1, udpPacketSerialized2, udpPacketSerialized3; protected IPacket tcpPacket1, tcpPacket2, tcpPacket3; protected byte[] tcpPacketSerialized1, tcpPacketSerialized2, tcpPacketSerialized3; protected IPacket ipprotoPacket, icmpPacket1, icmpPacket2; protected byte[] ipprotoPacketSerialized, icmpPacketSerialized1, icmpPacketSerialized2; protected IPacket arpPacket, arpPacket1, arpPacket2; protected byte[] arpPacketSerialized, arpPacketSerialized1, arpPacketSerialized2; @Before public void setUp() throws Exception { super.setUp(); storageSource = new MemoryStorageSource(); mockDeviceManager = new MockDeviceManager(); virtualRouting = new VirtualRouting(); netVirtManager = createMock(INetVirtManagerService.class); tunnelManager = createMock(ITunnelManagerService.class); // TODO: this should not be a nice mock! we should set up the // expectation for each of the test cases to check if they are // handled correctly. betterFlowCacheMgr = createNiceMock(IFlowCacheService.class); flowRecocileMgr = createMock(IFlowReconcileService.class); topology = createMock(ITopologyService.class); 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(IVirtualRoutingService.class, virtualRouting); fmc.addService(INetVirtManagerService.class, netVirtManager); fmc.addService(IFlowCacheService.class, betterFlowCacheMgr); fmc.addService(IFlowReconcileService.class, flowRecocileMgr); fmc.addService(ITopologyService.class, topology); fmc.addService(IRestApiService.class, ras); fmc.addService(IThreadPoolService.class, tp); fmc.addService(IEntityClassifierService.class, entityClassifier); fmc.addService(ITunnelManagerService.class, tunnelManager); storageSource.init(fmc); mockDeviceManager.init(fmc); virtualRouting.init(fmc); ras.init(fmc); mockControllerProvider.init(fmc); tp.init(fmc); entityClassifier.init(fmc); storageSource.startUp(fmc); mockDeviceManager.startUp(fmc); virtualRouting.startUp(fmc); ras.startUp(fmc); mockControllerProvider.startUp(fmc); tp.startUp(fmc); entityClassifier.startUp(fmc); // mock services // topology expect(topology.isAttachmentPointPort(anyLong(), anyShort())) .andReturn(true).anyTimes(); expect(topology.getL2DomainId(anyLong())).andReturn(1L).anyTimes(); expect(topology.isBroadcastDomainPort(anyLong(), anyShort())) .andReturn(false).anyTimes(); expect(topology.isConsistent(anyLong(), anyShort(), anyLong(), anyShort())) .andReturn(false).anyTimes(); expect(topology.isInSameBroadcastDomain(anyLong(), anyShort(), anyLong(), anyShort())) .andReturn(false).anyTimes(); // flow reconcile manager flowRecocileMgr.addFlowReconcileListener( anyObject(IFlowReconcileListener.class)); expectLastCall().anyTimes(); // netVirt manager expect(netVirtManager.getBroadcastSwitchPorts()) .andReturn(new ArrayList<SwitchPort>()).anyTimes(); // TODO: betterFlowCacheMgr should be mocked by each individual test replay(topology, flowRecocileMgr, betterFlowCacheMgr, netVirtManager); expect(tunnelManager.isTunnelEndpoint(anyObject(IDevice.class))) .andReturn(false).anyTimes(); replay(tunnelManager); // 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") .setPayload(new UDP() .setSourcePort((short) 5000) .setDestinationPort((short) 5001) .setPayload(new Data(new byte[] {0x01})))); this.udpPacketSerialized1 = udpPacket1.serialize(); this.udpPacket2 = 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") .setPayload(new UDP() .setSourcePort((short) 5000) .setDestinationPort((short) 33033))); this.udpPacketSerialized2 = udpPacket2.serialize(); this.udpPacket3 = 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") .setPayload(new UDP() .setSourcePort((short) 0) .setDestinationPort((short) 33033))); this.udpPacketSerialized3 = udpPacket3.serialize(); 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") .setPayload(new TCP() .setSourcePort((short) 5000) .setDestinationPort((short) 5001) .setPayload(new Data(new byte[] {0x01})))); this.tcpPacketSerialized1 = tcpPacket1.serialize(); 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") .setPayload(new TCP() .setSourcePort((short) 33000) .setDestinationPort((short) 5001))); this.tcpPacketSerialized2 = tcpPacket2.serialize(); this.tcpPacket3 = 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") .setPayload(new TCP() .setSourcePort((short) 33000) .setDestinationPort((short) 0))); this.tcpPacketSerialized3 = tcpPacket3.serialize(); this.ipprotoPacket = 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) .setProtocol((byte) 13) .setSourceAddress("192.168.1.1") .setDestinationAddress("192.168.1.3") .setPayload(new Data(new byte[] {1, 2, 3, 4, 5, 6, 8, 9, 10}))); this.ipprotoPacketSerialized = ipprotoPacket.serialize(); 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") .setPayload(new ICMP() .setIcmpType((byte) 8) .setPayload(new Data(new byte[] {1, 2, 3})))); this.icmpPacketSerialized1 = icmpPacket1.serialize(); this.icmpPacket2 = 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") .setPayload(new ICMP() .setIcmpType((byte) 0) .setPayload(new Data(new byte[] {1, 2, 3})))); this.icmpPacketSerialized2 = icmpPacket2.serialize(); // Not a real 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); this.arpPacketSerialized = arpPacket.serialize(); // Not a real ARP packet, test broadcast ACL (input only) this.arpPacket1 = new Ethernet() .setDestinationMACAddress("ff:ff:ff:ff:ff:ff") .setSourceMACAddress("00:00:00:00:00:01") .setEtherType(Ethernet.TYPE_ARP) .setPad(true); this.arpPacketSerialized1 = arpPacket1.serialize(); this.arpPacket2 = new Ethernet() .setDestinationMACAddress("ff:ff:ff:ff:ff:ff") .setSourceMACAddress("00:00:00:00:00:03") .setEtherType(Ethernet.TYPE_ARP) .setPad(true); this.arpPacketSerialized2 = arpPacket2.serialize(); } protected VirtualRouting getVirtualRouting() { return virtualRouting; } protected IStorageSourceService getStorageSource() { return storageSource; } /** * Add acl entries to storage at the beginning of each test */ private void addAcls(AclTest test) { if (macAcl1 != null) { test.addAcl(macAcl1); test.addAclEntry(macAclEntry1, macAclEntry2); } else { test.addAcl(acl1, acl2, acl3, acl4, acl5); test.addAclEntry(entry1_1, entry1_2, entry1_3, entry1_4, entry1_5); test.addAclEntry(entry2_1, entry2_2); test.addAclEntry(entry4_1, entry4_2, entry4_3, entry4_4); test.addAclEntry(entry5_1, entry5_2, entry5_3, entry5_4, entry5_5); } } /** * Common mockup environment for unicast tests */ private void testAclInternal(OFPacketIn pi, ListenerContext cntx, RoutingAction action, byte[] packetSerialized) throws Exception { IOFSwitch mockSwitch = createMock(IOFSwitch.class); expect(mockSwitch.getId()).andReturn(1L).anyTimes(); VirtualRouting routing = getVirtualRouting(); IControllerService mockControllerProvider = createMock(IControllerService.class); routing.setControllerProvider(mockControllerProvider); routing.setStorageSource(getStorageSource()); routing.readAclTablesFromStorage(); // Start recording the replay on the mocks replay(mockSwitch); Ethernet eth = new Ethernet(); eth.deserialize(packetSerialized, 0, packetSerialized.length); Integer srcIpAddr = null, dstIpAddr = null; if (eth.getEtherType() == Ethernet.TYPE_IPv4) { srcIpAddr = ((IPv4) eth.getPayload()).getSourceAddress(); dstIpAddr = ((IPv4) eth.getPayload()).getDestinationAddress(); } IDevice src = null, dst = null; /* * Learn pkt's source entity device, unless we need to. */ if (!skipSourceEntityLearn) { src = mockDeviceManager.learnEntity( Ethernet.toLong(eth.getSourceMACAddress()), null, srcIpAddr, 1L, 1); } /* * Learn pkt's destination entity device, unless we need to. */ if (!skipDestEntityLearn) { dst = mockDeviceManager.learnEntity( Ethernet.toLong(eth.getDestinationMACAddress()), null, dstIpAddr, 1L, 2); } // Trigger the packet in routing.receive(mockSwitch, pi, parseAndAnnotate(cntx, pi, src, dst)); // Get the annotation output for verification IRoutingDecision d = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); // Verify the replay matched our expectations verify(mockSwitch); if (action == RoutingAction.NONE) { assertNull(d); } else { assertNotNull(d); assertEquals(action, d.getRoutingAction()); assertEquals(1L, d.getSourcePort().getSwitchDPID()); assertEquals(pi.getInPort(), d.getSourcePort().getPort()); } } /** * Common implementation for setting up interfaces and if-Acl associations */ public void testAclCommon(VNSInterface iface, Map<String, Object> ifToAcl, byte[] packetSerialized, RoutingAction action) throws Exception { testAclCommon(iface, ifToAcl, packetSerialized, action, null); } public void testAclCommon(VNSInterface iface, Map<String, Object> ifToAcl, byte[] packetSerialized, RoutingAction action, ListenerContext paramCntx) throws Exception { ListenerContext cntx; if (paramCntx == null) { cntx = new ListenerContext(); } else { cntx = paramCntx; } List<VNSInterface> ifaces = new ArrayList<VNSInterface>(); ifaces.add(iface); INetVirtManagerService.bcStore.put(cntx, INetVirtManagerService.CONTEXT_SRC_IFACES, ifaces); INetVirtManagerService.bcStore.put(cntx, INetVirtManagerService.CONTEXT_DST_IFACES, ifaces); OFPacketIn pi = new OFPacketIn() .setBufferId(-1) .setInPort((short) 1) .setPacketData(packetSerialized) .setReason(OFPacketInReason.NO_MATCH) .setTotalLength((short) packetSerialized.length); // Clear ACL from storage IStorageSourceService storageSource = getStorageSource(); clearStorage(storageSource); AclTest test = new AclTest(); addAcls(test); test.addIfAcl(ifToAcl); test.writeToStorage(storageSource); testAclInternal(pi, cntx, action, packetSerialized); } /** * No ACL, should pass by default */ @Test public void testNoAcl() throws Exception { ListenerContext cntx = new ListenerContext(); List<VNSInterface> ifaces = new ArrayList<VNSInterface>(); ifaces.add(if1); INetVirtManagerService.bcStore.put(cntx, INetVirtManagerService.CONTEXT_SRC_IFACES, ifaces); INetVirtManagerService.bcStore.put(cntx, INetVirtManagerService.CONTEXT_DST_IFACES, ifaces); OFPacketIn pi = new OFPacketIn() .setBufferId(-1) .setInPort((short) 1) .setPacketData(udpPacketSerialized1) .setReason(OFPacketInReason.NO_MATCH) .setTotalLength((short) udpPacketSerialized1.length); // Clear ACL from storage IStorageSourceService storageSource = getStorageSource(); clearStorage(storageSource); testAclInternal(pi, cntx, RoutingAction.FORWARD, udpPacketSerialized1); } /** * Add ACL with no entry, default to deny, should drop */ @Test public void testDefaultDeny() throws Exception { testAclCommon(if3, ifAcl3out, udpPacketSerialized2, RoutingAction.DROP); } /** * Add ACL ip exact: match on input, should drop */ @Test public void testIpExactIn() throws Exception { testAclCommon(if1, ifAcl1in, udpPacketSerialized1, RoutingAction.DROP); } /** * Add ACL ip exact: match on output, should drop */ @Test public void testIpExactOut() throws Exception { testAclCommon(if1, ifAcl1out, udpPacketSerialized1, RoutingAction.DROP); } /** * Add ACL: match on subnet on output, should pass */ @Test public void testIpSubnetMatch() throws Exception { testAclCommon(if1, ifAcl1out, udpPacketSerialized2, RoutingAction.FORWARD); } /** * Same as above except we add ACL for parent interface (if2). * Since if2 acl has a higher priority, and matches with deny, * the packet should should be dropped. */ @Test public void testInterfacePriority() throws Exception { ListenerContext cntx = new ListenerContext(); List<VNSInterface> ifaces = new ArrayList<VNSInterface>(); ifaces.add(if1); INetVirtManagerService.bcStore.put(cntx, INetVirtManagerService.CONTEXT_SRC_IFACES, ifaces); INetVirtManagerService.bcStore.put(cntx, INetVirtManagerService.CONTEXT_DST_IFACES, ifaces); OFPacketIn pi = new OFPacketIn() .setBufferId(-1) .setInPort((short) 1) .setPacketData(udpPacketSerialized2) .setReason(OFPacketInReason.NO_MATCH) .setTotalLength((short) udpPacketSerialized2.length); // Setup ACL IStorageSourceService storageSource = getStorageSource(); clearStorage(storageSource); AclTest test = new AclTest(); addAcls(test); test.addIfAcl(ifAcl1out); test.addIfAcl(ifAcl2out); test.writeToStorage(storageSource); testAclInternal(pi, cntx, RoutingAction.DROP, udpPacketSerialized2); } /** * Test ipproto match ("13"), should drop */ @Test public void testIpprotoMatch() throws Exception { testAclCommon(if1, ifAcl1out, ipprotoPacketSerialized, RoutingAction.DROP); } /** * Test icmp match type 8, should drop */ @Test public void testIcmpMatch() throws Exception { testAclCommon(if1, ifAcl1out, icmpPacketSerialized1, RoutingAction.DROP); } /** * Test icmp mismatch type 0, should forward */ @Test public void testIcmpNoMatch() throws Exception { testAclCommon(if1, ifAcl1out, icmpPacketSerialized2, RoutingAction.FORWARD); } /** * Test udp matched port, should deny */ @Test public void testUdpPortEqMatch() throws Exception { testAclCommon(if4, ifAcl4in, udpPacketSerialized1, RoutingAction.DROP); } /** * Test udp match on dst port only, should forward */ @Test public void testUdpPortEqPartialMatch() throws Exception { testAclCommon(if4, ifAcl4in, udpPacketSerialized2, RoutingAction.FORWARD); } /** * Test udp match to any port, should forward */ @Test public void testUdpPortEqNoMatch() throws Exception { testAclCommon(if4, ifAcl4in, udpPacketSerialized3, RoutingAction.FORWARD); } /** * Test tcp mismatched port, should forward */ @Test public void testTcpPortNeqNoMatch() throws Exception { testAclCommon(if4, ifAcl4in, tcpPacketSerialized1, RoutingAction.FORWARD); } /** * Test tcp matched port, should forward */ @Test public void testTcpPortNeqPartialMatch() throws Exception { testAclCommon(if4, ifAcl4in, tcpPacketSerialized2, RoutingAction.FORWARD); } /** * Test tcp matched port, should deny */ @Test public void testTcpPortNeqMatch() throws Exception { testAclCommon(if4, ifAcl4in, tcpPacketSerialized3, RoutingAction.DROP); } /** * Test matched mac and ethertype, should deny */ @Test public void testMacArpMatch() throws Exception { testAclCommon(if5, ifAcl5in, arpPacketSerialized, RoutingAction.DROP); } /** * Test mac src wildcard, exact dst, should deny */ @Test public void testMacIpMatch() throws Exception { testAclCommon(if5, ifAcl5in, udpPacketSerialized2, RoutingAction.DROP); } /** * Test mac src/dst wildcard, should permit */ @Test public void testMacWildcard() throws Exception { testAclCommon(if5, ifAcl5in, udpPacketSerialized1, RoutingAction.FORWARD); } /** * Test broadcast ACL, should allow */ @Test public void testBroadcast() throws Exception { testAclCommon(if5, ifAcl5in, arpPacketSerialized1, RoutingAction.MULTICAST); } /** * Test broadcast ACL deny, in this cast there is no action annotation */ @Test public void testBroadcastDROP() throws Exception { testAclCommon(if5, ifAcl5in, arpPacketSerialized2, RoutingAction.NONE); } /* * Private variables used in MAC address matching ACL tests below. */ private boolean skipSourceEntityLearn; private boolean skipDestEntityLearn; private VNSInterface macNetVirtIf1; private Map<String, Object> macIf1; private HashMap<String, Object> macAcl1 = null; private Map<String, Object> macAclEntry1 = null; private Map<String, Object> macAclEntry2 = null; /* * macAclTestInit * * Initialize the acl and interface access-group used in the mac tests * that follow. */ private void macAclTestsInit () { macAcl1 = new HashMap<String, Object>(); macAcl1.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|macAcl1"); macAcl1.put(VirtualRouting.NAME_COLUMN_NAME, "macAcl1"); macAcl1.put(VirtualRouting.PRIORITY_COLUMN_NAME, 1000); macNetVirtIf1 = new VNSInterface("macNetVirtIf1", netVirt, null, null); macIf1 = new HashMap<String, Object>(); macIf1.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|macNetVirtIf1|netVirt|macAcl1|in"); macIf1.put(VirtualRouting.INTERFACE_COLUMN_NAME, "netVirt|macNetVirtIf1"); macIf1.put(VirtualRouting.ACL_NAME_COLUMN_NAME, "netVirt|macAcl1"); macIf1.put(VirtualRouting.IN_OUT_COLUMN_NAME, "in"); } /* * runMacAclTests * * Run variuos mac address match based ACL tests. */ private void runMacAclTests ( String asMac, /* Configured source mac */ String adMac, /* Configured dest mac */ int avlan, /* Configured vlan id */ short aetherType, /* Configured ether type */ String aaction, /* Configured match action */ boolean learnSource, /* Should src dvc be null ? */ boolean learnDest, /* Should dst dvc be null ? */ String psMac, /* Pkt's source mac */ String pdMac, /* Pkt's dest mac */ int pvlan, /* Pkt's vlan id */ short petherType, /* Pkt's ether type */ RoutingAction routingAction) /* Expected routing action */ { IPacket samplePkt; /* * Create a sample packet to feed based on the packet parameters passed * in. */ samplePkt = new Ethernet() .setDestinationMACAddress(psMac) .setSourceMACAddress(pdMac) .setVlanID((short) pvlan) .setEtherType(petherType) .setPayload( new IPv4() .setTtl((byte) 128) .setSourceAddress("192.168.1.1") .setDestinationAddress("192.168.1.2") .setPayload(new UDP() .setSourcePort((short) 5000) .setDestinationPort((short) 5001) .setPayload(new Data(new byte[] {0x01})))); byte[] samplePktSerialized = samplePkt.serialize(); /* * Create acl entries configured as desired. */ macAclEntry1 = new HashMap<String, Object>(); macAclEntry1.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|macAcl1|10"); macAclEntry1.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|macAcl1"); macAclEntry1.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "10"); macAclEntry1.put(VirtualRouting.TYPE_COLUMN_NAME, "mac"); macAclEntry1.put(VirtualRouting.SRC_MAC_COLUMN_NAME, asMac); macAclEntry1.put(VirtualRouting.DST_MAC_COLUMN_NAME, adMac); macAclEntry1.put(VirtualRouting.VLAN_COLUMN_NAME, avlan); macAclEntry1.put(VirtualRouting.ETHER_TYPE_COLUMN_NAME, aetherType); macAclEntry1.put(VirtualRouting.ACTION_COLUMN_NAME, aaction); /* * Have a default explicit rule that does the opposite of the above * rule. i.e, if the above rule tries to match and 'permit', do a * match all 'deny', and vice versa. */ macAclEntry2 = new HashMap<String, Object>(); macAclEntry2.put(VirtualRouting.ID_COLUMN_NAME, "netVirt|macAcl1|20"); macAclEntry2.put(VirtualRouting.ACL_ENTRY_VNS_ACL_COLUMN_NAME, "netVirt|macAcl1"); macAclEntry2.put(VirtualRouting.ACL_ENTRY_RULE_COLUMN_NAME, "20"); macAclEntry2.put(VirtualRouting.TYPE_COLUMN_NAME, "mac"); macAclEntry2.put(VirtualRouting.SRC_MAC_COLUMN_NAME, ""); macAclEntry2.put(VirtualRouting.DST_MAC_COLUMN_NAME, ""); macAclEntry2.put(VirtualRouting.ETHER_TYPE_COLUMN_NAME, aetherType); macAclEntry2.put(VirtualRouting.ACTION_COLUMN_NAME, aaction.equals("permit") ? "deny" : "permit"); /* * Set the private variables appropriately, so that later in the call * chain, source and/or destination device entity learning process is * skipped, if necessary for this test run. */ skipSourceEntityLearn = learnSource; skipDestEntityLearn = learnDest; /* * Invoke the packet feed and acl match routines. */ try { testAclCommon(macNetVirtIf1, macIf1, samplePktSerialized, routingAction); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return; } /* * testMacAclTests * * Fields: * aSrcMac aDstMac aVlan aEtherType pSrcMac pDstMac pVlan pEtherType * * Values: * pMac : Known and UnKnown, matching and non-matching * Unicast, Multicast and Broadcast MAC addresses * pVlan : <0 - 4095> {0, 10, 4096} * pEtherType: <0 - 255> {IPv4, ARP, IPv6} * * aMac : Unicast, Multicast and Broadcast * aVlan : <0 - 4095> * aEtherType: <0 - 255> * aAction : permit, deny * * Action: * enum RoutingAction * * XXX Generate more tests, given the core logic already provided above. * */ @Test public void testMacAclTests () throws Exception { macAclTestsInit(); /* * XXX These calls have been intentionally written in very wide lines, * so that tests comparison is easy, in wide terminals. */ /* * Run tests with both source and destination entities learnt. */ runMacAclTests("00:00:00:00:00:01", "00:00:00:00:00:01", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, "permit", false, false, "00:00:00:00:00:01", "00:00:00:00:00:01", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, RoutingAction.FORWARD); // Match and forward runMacAclTests("00:00:00:00:00:01", "00:00:00:00:00:01", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, "deny", false, false, "00:00:00:00:00:01", "00:00:00:00:00:01", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, RoutingAction.DROP); // Match and drop runMacAclTests("00:00:00:00:00:01", "00:00:00:00:00:01", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, "deny", false, false, "00:00:00:00:00:01", "00:00:00:00:00:02", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, RoutingAction.FORWARD); // No-Match and forward (by second all wild cards rule) runMacAclTests("00:00:00:00:00:01", "00:00:00:00:00:01", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, "permit", false, false, "00:00:00:00:00:01", "00:00:00:00:00:02", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, RoutingAction.DROP); // No-Match and drop (by second all wild cards rule) /* * Run tests with source and/or dest entities learning skipped, for unicast and broadcast addresses. */ runMacAclTests("00:00:00:00:00:01", "00:00:00:00:00:01", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, "permit", false, false, "00:00:00:00:00:01", "00:00:00:00:00:01", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, RoutingAction.FORWARD); // Match and forward runMacAclTests("00:00:00:00:00:01", "00:00:00:00:00:01", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, "permit", false, true, "00:00:00:00:00:01", "00:00:00:00:00:02", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, RoutingAction.FORWARD); // No-Match, yet forward as there is no dest device runMacAclTests("00:00:00:00:00:01", "00:00:00:00:00:01", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, "permit", true, false, "00:00:00:00:00:01", "00:00:00:00:00:01", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, RoutingAction.NONE); // Match but still deny as there is no source device runMacAclTests("00:00:00:00:00:01", "00:00:00:00:00:01", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, "permit", true, true, "00:00:00:00:00:01", "00:00:00:00:00:01", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, RoutingAction.NONE); // Match but still deny as there is no source device runMacAclTests("ff:ff:ff:ff:ff:ff", "ff:ff:ff:ff:ff:ff", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, "permit", false, false, "ff:ff:ff:ff:ff:ff", "ff:ff:ff:ff:ff:ff", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, RoutingAction.MULTICAST); // Match and forward runMacAclTests("ff:ff:ff:ff:ff:ff", "ff:ff:ff:ff:ff:ff", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, "deny", false, true, "ff:ff:ff:ff:ff:ff", "ff:ff:ff:ff:ff:ff", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, RoutingAction.NONE); // Match and drop even though is no dest device runMacAclTests("ff:ff:ff:ff:ff:ff", "ff:ff:ff:ff:ff:ff", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, "permit", true, false, "ff:ff:ff:ff:ff:ff", "ff:ff:ff:ff:ff:ff", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, RoutingAction.NONE); // Match but still deny as there is no source device runMacAclTests("ff:ff:ff:ff:ff:ff", "ff:ff:ff:ff:ff:ff", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, "permit", true, true, "ff:ff:ff:ff:ff:ff", "ff:ff:ff:ff:ff:ff", VNSAccessControlListEntry.VLAN_ALL, Ethernet.TYPE_IPv4, RoutingAction.NONE); // Match but still deny as there is no source device /* * Do some tests with valid vlan tags. */ runMacAclTests("00:00:00:00:00:01", "00:00:00:00:00:01", 1, Ethernet.TYPE_IPv4, "permit", false, false, "00:00:00:00:00:01", "00:00:00:00:00:01", 1, Ethernet.TYPE_IPv4, RoutingAction.FORWARD); // Match and forward runMacAclTests("00:00:00:00:00:01", "00:00:00:00:00:01", 1, Ethernet.TYPE_IPv4, "permit", false, true, "00:00:00:00:00:01", "00:00:00:00:00:02", 1, Ethernet.TYPE_IPv4, RoutingAction.FORWARD); // No-Match, yet forward as there is no dest device runMacAclTests("00:00:00:00:00:01", "00:00:00:00:00:01", 1, Ethernet.TYPE_IPv4, "permit", true, false, "00:00:00:00:00:01", "00:00:00:00:00:01", 1, Ethernet.TYPE_IPv4, RoutingAction.NONE); // Match but still deby as there is no source device runMacAclTests("00:00:00:00:00:01", "00:00:00:00:00:01", 1, Ethernet.TYPE_IPv4, "permit", true, true, "00:00:00:00:00:01", "00:00:00:00:00:01", 1, Ethernet.TYPE_IPv4, RoutingAction.NONE); // Match but still deny as there is no source device -- REVIST THIS /* * Reset the variables, as mac tests are complete. */ macAcl1 = null; macAclEntry1 = null; macAclEntry2 = null; } @Test public void testAclIn() throws Exception { ListenerContext cntx = new ListenerContext(); List<VNSInterface> ifaces = new ArrayList<VNSInterface>(); ifaces.add(if3); INetVirtManagerService.bcStore.put(cntx, INetVirtManagerService.CONTEXT_SRC_IFACES, ifaces); List<VNSInterface> ifaces2 = new ArrayList<VNSInterface>(); ifaces2.add(if2); INetVirtManagerService.bcStore.put(cntx, INetVirtManagerService.CONTEXT_DST_IFACES, ifaces2); OFPacketIn pi = new OFPacketIn() .setBufferId(-1) .setInPort((short) 1) .setPacketData(udpPacketSerialized1) .setReason(OFPacketInReason.NO_MATCH) .setTotalLength((short) udpPacketSerialized1.length); // Setup ACL IStorageSourceService storageSource = getStorageSource(); clearStorage(storageSource); AclTest test = new AclTest(); addAcls(test); test.addIfAcl(ifAcl2in); test.writeToStorage(storageSource); testAclInternal(pi, cntx, RoutingAction.FORWARD, udpPacketSerialized1); } @Test public void testAclOut() throws Exception { ListenerContext cntx = new ListenerContext(); List<VNSInterface> ifaces = new ArrayList<VNSInterface>(); ifaces.add(if3); INetVirtManagerService.bcStore.put(cntx, INetVirtManagerService.CONTEXT_SRC_IFACES, ifaces); List<VNSInterface> ifaces2 = new ArrayList<VNSInterface>(); ifaces2.add(if2); INetVirtManagerService.bcStore.put(cntx, INetVirtManagerService.CONTEXT_DST_IFACES, ifaces2); OFPacketIn pi = new OFPacketIn() .setBufferId(-1) .setInPort((short) 1) .setPacketData(udpPacketSerialized1) .setReason(OFPacketInReason.NO_MATCH) .setTotalLength((short) udpPacketSerialized1.length); // Setup ACL IStorageSourceService storageSource = getStorageSource(); clearStorage(storageSource); AclTest test = new AclTest(); addAcls(test); test.addIfAcl(ifAcl2out); test.writeToStorage(storageSource); testAclInternal(pi, cntx, RoutingAction.DROP, udpPacketSerialized1); } /** * Test Acl Annotation for "test packet-in" message */ @Test public void testAclAnnotationOfExplainPacket() throws Exception { // set appropriate context ListenerContext cntx = new ListenerContext(); NetVirtExplainPacket.ExplainStore.put(cntx, NetVirtExplainPacket.KEY_EXPLAIN_PKT, NetVirtExplainPacket.VAL_EXPLAIN_PKT); NetVirtExplainPacket.ExplainPktRoute epr = new NetVirtExplainPacket.ExplainPktRoute(); NetVirtExplainPacket.ExplainRouteStore.put(cntx, NetVirtExplainPacket.KEY_EXPLAIN_PKT_ROUTE, epr); testAclCommon(if5, ifAcl5in, udpPacketSerialized1, RoutingAction.FORWARD, cntx); // Now check if the NetVirt name and Input ACL Name are correctly Annotated String aclName = NetVirtExplainPacket.ExplainStore.get(cntx, NetVirtExplainPacket.KEY_EXPLAIN_PKT_INP_ACL_NAME); assertTrue(aclName.equals("acl5")); String aclResult = NetVirtExplainPacket.ExplainStore.get(cntx, NetVirtExplainPacket.KEY_EXPLAIN_PKT_INP_ACL_RESULT); assertTrue(aclResult.equals("ACL_PERMIT")); String aclEntry = NetVirtExplainPacket.ExplainStore.get(cntx, NetVirtExplainPacket.KEY_EXPLAIN_PKT_INP_ACL_ENTRY); assertTrue(aclEntry.contains("520 permit mac any any")); // Check that the NetVirt Name is annotated String srcNetVirt = NetVirtExplainPacket.ExplainStore.get(cntx, NetVirtExplainPacket.KEY_EXPLAIN_PKT_SRC_NetVirt); assertTrue(srcNetVirt.equals("netVirt")); String dstNetVirt = NetVirtExplainPacket.ExplainStore.get(cntx, NetVirtExplainPacket.KEY_EXPLAIN_PKT_DST_NetVirt); assertTrue(dstNetVirt.equals("netVirt")); // Check the annotation of output ACL ListenerContext outCntx = new ListenerContext(); NetVirtExplainPacket.ExplainStore.put(outCntx, NetVirtExplainPacket.KEY_EXPLAIN_PKT, NetVirtExplainPacket.VAL_EXPLAIN_PKT); NetVirtExplainPacket.ExplainPktRoute outEpr = new NetVirtExplainPacket.ExplainPktRoute(); NetVirtExplainPacket.ExplainRouteStore.put(outCntx, NetVirtExplainPacket.KEY_EXPLAIN_PKT_ROUTE, outEpr); // Run the command testAclCommon(if3, ifAcl3out, udpPacketSerialized2, RoutingAction.DROP, outCntx); aclName = NetVirtExplainPacket.ExplainStore.get(outCntx, NetVirtExplainPacket.KEY_EXPLAIN_PKT_OUT_ACL_NAME); assertTrue(aclName.equals("acl3")); aclResult = NetVirtExplainPacket.ExplainStore.get(outCntx, NetVirtExplainPacket.KEY_EXPLAIN_PKT_OUT_ACL_RESULT); assertTrue(aclResult.equals("ACL_DENY")); aclEntry = NetVirtExplainPacket.ExplainStore.get(outCntx, NetVirtExplainPacket.KEY_EXPLAIN_PKT_OUT_ACL_ENTRY); assertTrue(aclEntry.contains("Implicit deny")); // Check that non Explain Packets are not annotated ListenerContext noAnnotateCntx = new ListenerContext(); testAclCommon(if3, ifAcl3out, udpPacketSerialized2, RoutingAction.DROP, noAnnotateCntx); aclName = null; aclName = NetVirtExplainPacket.ExplainStore.get(noAnnotateCntx, NetVirtExplainPacket.KEY_EXPLAIN_PKT_OUT_ACL_NAME); assertTrue(aclName == null); // Verify that the context contains the NetVirt and ACL annotations } }