/** * Copyright 2011, Big Switch Networks, Inc. * Originally created by Amer Tahir * * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 * * 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 net.floodlightcontroller.firewall; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import static org.easymock.EasyMock.capture; import static org.easymock.EasyMock.reset; import static org.junit.Assert.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.internal.IOFSwitchService; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.util.AppCookie; import net.floodlightcontroller.debugcounter.IDebugCounterService; import net.floodlightcontroller.debugcounter.MockDebugCounterService; import net.floodlightcontroller.packet.ARP; import net.floodlightcontroller.packet.Data; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPacket; import net.floodlightcontroller.packet.IPv4; import net.floodlightcontroller.packet.TCP; import net.floodlightcontroller.packet.UDP; import net.floodlightcontroller.restserver.IRestApiService; import net.floodlightcontroller.restserver.RestApiServer; import net.floodlightcontroller.routing.IRoutingDecision; import net.floodlightcontroller.routing.IRoutingService; import net.floodlightcontroller.storage.IStorageSourceService; import net.floodlightcontroller.storage.memory.MemoryStorageSource; import net.floodlightcontroller.test.FloodlightTestCase; import org.easymock.Capture; import org.easymock.CaptureType; import org.easymock.EasyMock; import org.junit.Before; import org.junit.Test; import org.projectfloodlight.openflow.protocol.OFFactories; import org.projectfloodlight.openflow.protocol.OFPacketIn; import org.projectfloodlight.openflow.protocol.OFPacketInReason; import org.projectfloodlight.openflow.protocol.OFVersion; import org.projectfloodlight.openflow.protocol.match.MatchField; import org.projectfloodlight.openflow.types.DatapathId; import org.projectfloodlight.openflow.types.EthType; import org.projectfloodlight.openflow.types.IPv4Address; import org.projectfloodlight.openflow.types.IPv4AddressWithMask; import org.projectfloodlight.openflow.types.IpProtocol; import org.projectfloodlight.openflow.types.MacAddress; import org.projectfloodlight.openflow.types.Masked; import org.projectfloodlight.openflow.types.OFBufferId; import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.TransportPort; import org.projectfloodlight.openflow.types.U64; /** * Unit test for stateless firewall implemented as a Google Summer of Code project. * * @author Amer Tahir */ public class FirewallTest extends FloodlightTestCase { protected IRoutingService routingService; protected FloodlightContext cntx; protected OFPacketIn packetIn; protected IOFSwitch sw; protected IPacket tcpPacket; protected IPacket broadcastARPPacket; protected IPacket ARPReplyPacket; protected IPacket broadcastIPPacket; protected IPacket tcpPacketReply; protected IPacket broadcastMalformedPacket; private Firewall firewall; private MockDebugCounterService debugCounterService; public static String TestSwitch1DPID = "00:00:00:00:00:00:00:01"; private static final short APP_ID = 30; static { AppCookie.registerApp(APP_ID, "Firewall"); } private static final U64 DENY_BCAST_COOKIE = AppCookie.makeCookie(APP_ID, 0xaaaaaaL); private static final U64 ALLOW_BCAST_COOKIE = AppCookie.makeCookie(APP_ID, 0x555555L); private static final U64 RULE_MISS_COOKIE = AppCookie.makeCookie(APP_ID, 0xffffffL); @Override @Before public void setUp() throws Exception { super.setUp(); cntx = new FloodlightContext(); mockFloodlightProvider = getMockFloodlightProvider(); mockSwitchManager = getMockSwitchService(); debugCounterService = new MockDebugCounterService(); firewall = new Firewall(); MemoryStorageSource storageService = new MemoryStorageSource(); RestApiServer restApi = new RestApiServer(); routingService = createMock(IRoutingService.class); // Mock switches DatapathId dpid = DatapathId.of(TestSwitch1DPID); sw = EasyMock.createNiceMock(IOFSwitch.class); expect(sw.getId()).andReturn(dpid).anyTimes(); expect(sw.getOFFactory()).andReturn(OFFactories.getFactory(OFVersion.OF_13)).anyTimes(); replay(sw); // Load the switch map Map<DatapathId, IOFSwitch> switches = new HashMap<DatapathId, IOFSwitch>(); switches.put(dpid, sw); mockSwitchManager.setSwitches(switches); FloodlightModuleContext fmc = new FloodlightModuleContext(); fmc.addService(IFloodlightProviderService.class, mockFloodlightProvider); fmc.addService(IDebugCounterService.class, debugCounterService); fmc.addService(IOFSwitchService.class, mockSwitchManager); fmc.addService(IFirewallService.class, firewall); fmc.addService(IStorageSourceService.class, storageService); fmc.addService(IRestApiService.class, restApi); fmc.addService(IRoutingService.class, routingService); debugCounterService.init(fmc); storageService.init(fmc); restApi.init(fmc); firewall.init(fmc); debugCounterService.startUp(fmc); storageService.startUp(fmc); firewall.startUp(fmc); // Build our test packet this.tcpPacket = new Ethernet() .setDestinationMACAddress("00:11:22:33:44:55") .setSourceMACAddress("00:44:33:22:11:00") .setVlanID((short) 42) .setEtherType(EthType.IPv4) .setPayload( new IPv4() .setTtl((byte) 128) .setSourceAddress("192.168.1.1") .setDestinationAddress("192.168.1.2") .setPayload(new TCP() .setSourcePort((short) 81) .setDestinationPort((short) 80) .setPayload(new Data(new byte[] {0x01})))); // Build a broadcast ARP packet this.broadcastARPPacket = new Ethernet() .setDestinationMACAddress("FF:FF:FF:FF:FF:FF") .setSourceMACAddress("00:44:33:22:11:00") .setVlanID((short) 42) .setEtherType(EthType.ARP) .setPayload( new ARP() .setHardwareType(ARP.HW_TYPE_ETHERNET) .setProtocolType(ARP.PROTO_TYPE_IP) .setOpCode(ARP.OP_REQUEST) .setHardwareAddressLength((byte)6) .setProtocolAddressLength((byte)4) .setSenderHardwareAddress(MacAddress.of("00:44:33:22:11:00")) .setSenderProtocolAddress(IPv4Address.of("192.168.1.1")) .setTargetHardwareAddress(MacAddress.of("00:00:00:00:00:00")) .setTargetProtocolAddress(IPv4Address.of("192.168.1.2")) .setPayload(new Data(new byte[] {0x01}))); // Build a ARP packet this.ARPReplyPacket = new Ethernet() .setDestinationMACAddress("00:44:33:22:11:00") .setSourceMACAddress("00:11:22:33:44:55") .setVlanID((short) 42) .setEtherType(EthType.ARP) .setPayload( new ARP() .setHardwareType(ARP.HW_TYPE_ETHERNET) .setProtocolType(ARP.PROTO_TYPE_IP) .setOpCode(ARP.OP_REQUEST) .setHardwareAddressLength((byte)6) .setProtocolAddressLength((byte)4) .setSenderHardwareAddress(MacAddress.of("00:11:22:33:44:55")) .setSenderProtocolAddress(IPv4Address.of("192.168.1.2")) .setTargetHardwareAddress(MacAddress.of("00:44:33:22:11:00")) .setTargetProtocolAddress(IPv4Address.of("192.168.1.1")) .setPayload(new Data(new byte[] {0x01}))); // Build a broadcast IP packet this.broadcastIPPacket = new Ethernet() .setDestinationMACAddress("FF:FF:FF:FF:FF:FF") .setSourceMACAddress("00:44:33:22:11:00") .setVlanID((short) 42) .setEtherType(EthType.IPv4) .setPayload( new IPv4() .setTtl((byte) 128) .setSourceAddress("192.168.1.1") .setDestinationAddress("192.168.1.255") .setPayload(new UDP() .setSourcePort((short) 5000) .setDestinationPort((short) 5001) .setPayload(new Data(new byte[] {0x01})))); // Build a malformed broadcast packet this.broadcastMalformedPacket = new Ethernet() .setDestinationMACAddress("FF:FF:FF:FF:FF:FF") .setSourceMACAddress("00:44:33:22:11:00") .setVlanID((short) 42) .setEtherType(EthType.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.tcpPacketReply = new Ethernet() .setDestinationMACAddress("00:44:33:22:11:00") .setSourceMACAddress("00:11:22:33:44:55") .setVlanID((short) 42) .setEtherType(EthType.IPv4) .setPayload( new IPv4() .setTtl((byte) 128) .setSourceAddress("192.168.1.2") .setDestinationAddress("192.168.1.1") .setPayload(new TCP() .setSourcePort((short) 80) .setDestinationPort((short) 81) .setPayload(new Data(new byte[] {0x02})))); } protected void setPacketIn(IPacket packet) { byte[] serializedPacket = packet.serialize(); // Build the PacketIn this.packetIn = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn() .setBufferId(OFBufferId.NO_BUFFER) .setMatch(OFFactories.getFactory(OFVersion.OF_13).buildMatch().setExact(MatchField.IN_PORT, OFPort.of(1)).build()) .setData(serializedPacket) .setReason(OFPacketInReason.NO_MATCH) .build(); // Add the packet to the context store IFloodlightProviderService.bcStore. put(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD, (Ethernet)packet); } public boolean compareU64ListsOrdered(List<Masked<U64>> a,List<Masked<U64>> b){ Object[] aArray = a.toArray(); Object[] bArray = b.toArray(); if (aArray.length != bArray.length) return false; for(int i = 0; i<aArray.length; i++){ if(aArray[i].equals(bArray[i]) == false){ return false; } } return true; } @Test public void enableFirewall() throws Exception{ Capture<ArrayList<Masked<U64>>> wc1 = EasyMock.newCapture(CaptureType.ALL); routingService.handleRoutingDecisionChange(capture(wc1)); ArrayList<Masked<U64>> test_changes = new ArrayList<Masked<U64>>(); replay(routingService); firewall.enableFirewall(true); verify(routingService); test_changes.add(Masked.of(Firewall.DEFAULT_COOKIE, AppCookie.getAppFieldMask())); assertTrue(compareU64ListsOrdered(wc1.getValue(),test_changes)); } @Test public void testNoRules() throws Exception { // enable firewall first firewall.enableFirewall(true); // simulate a packet-in event this.setPacketIn(tcpPacket); firewall.receive(sw, this.packetIn, cntx); verify(sw); assertEquals(0, firewall.rules.size()); IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); // no rules to match, so firewall should deny assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.DROP); assertEquals(RULE_MISS_COOKIE, decision.getDescriptor()); } @Test public void testReadRulesFromStorage() throws Exception { Capture<ArrayList<Masked<U64>>> wc1 = EasyMock.newCapture(CaptureType.ALL); routingService.handleRoutingDecisionChange(capture(wc1)); ArrayList<Masked<U64>> test_changes = new ArrayList<Masked<U64>>(); U64 singleRuleMask = AppCookie.getAppFieldMask().or(AppCookie.getUserFieldMask()); // add 2 rules first FirewallRule rule = new FirewallRule(); rule.in_port = OFPort.of(2); rule.dl_src = MacAddress.of("00:00:00:00:00:01"); rule.dl_dst = MacAddress.of("00:00:00:00:00:02"); rule.priority = 1; rule.action = FirewallRule.FirewallAction.DROP; replay(routingService); firewall.addRule(rule); verify(routingService); test_changes.add(Masked.of(AppCookie.makeCookie(APP_ID, rule.ruleid), singleRuleMask)); test_changes.add(Masked.of(RULE_MISS_COOKIE, singleRuleMask)); assertEquals(compareU64ListsOrdered(wc1.getValue(),test_changes),true); reset(routingService); // next rule wc1 = EasyMock.newCapture(CaptureType.ALL); test_changes = new ArrayList<Masked<U64>>(); routingService.handleRoutingDecisionChange(capture(wc1)); rule = new FirewallRule(); rule.in_port = OFPort.of(3); rule.dl_src = MacAddress.of("00:00:00:00:00:02"); rule.dl_dst = MacAddress.of("00:00:00:00:00:01"); rule.nw_proto = IpProtocol.TCP; rule.any_nw_proto = false; rule.tp_dst = TransportPort.of(80); rule.priority = 2; rule.action = FirewallRule.FirewallAction.ALLOW; replay(routingService); firewall.addRule(rule); verify(routingService); test_changes.add(Masked.of(AppCookie.makeCookie(APP_ID, rule.ruleid), singleRuleMask)); test_changes.add(Masked.of(RULE_MISS_COOKIE, singleRuleMask)); assertTrue(compareU64ListsOrdered(wc1.getValue(),test_changes)); reset(routingService); List<FirewallRule> rules = firewall.readRulesFromStorage(); // verify rule 1 FirewallRule r = rules.get(0); assertEquals(r.in_port, OFPort.of(2)); assertEquals(r.priority, 1); assertEquals(r.dl_src, MacAddress.of("00:00:00:00:00:01")); assertEquals(r.dl_dst, MacAddress.of("00:00:00:00:00:02")); assertEquals(r.action, FirewallRule.FirewallAction.DROP); // verify rule 2 r = rules.get(1); assertEquals(r.in_port, OFPort.of(3)); assertEquals(r.priority, 2); assertEquals(r.dl_src, MacAddress.of("00:00:00:00:00:02")); assertEquals(r.dl_dst, MacAddress.of("00:00:00:00:00:01")); assertEquals(r.nw_proto, IpProtocol.TCP); assertEquals(r.tp_dst, TransportPort.of(80)); assertEquals(r.any_nw_proto, false); assertEquals(r.action, FirewallRule.FirewallAction.ALLOW); } @Test public void testRuleInsertionIntoStorage() throws Exception { // add TCP rule FirewallRule rule = new FirewallRule(); rule.nw_proto = IpProtocol.TCP; rule.any_nw_proto = false; rule.priority = 1; firewall.addRule(rule); List<Map<String, Object>> rulesFromStorage = firewall.getStorageRules(); assertEquals(1, rulesFromStorage.size()); assertEquals(Integer.parseInt((String)rulesFromStorage.get(0).get("ruleid")), rule.ruleid); } @Test public void testRuleDeletion() throws Exception { // add TCP rule FirewallRule rule = new FirewallRule(); rule.nw_proto = IpProtocol.TCP; rule.any_nw_proto = false; rule.priority = 1; firewall.addRule(rule); int rid = rule.ruleid; reset(routingService); Capture<ArrayList<Masked<U64>>> wc1 = EasyMock.newCapture(CaptureType.ALL); routingService.handleRoutingDecisionChange(capture(wc1)); ArrayList<Masked<U64>> test_changes = new ArrayList<Masked<U64>>(); U64 singleRuleMask = AppCookie.getAppFieldMask().or(AppCookie.getUserFieldMask()); List<Map<String, Object>> rulesFromStorage = firewall.getStorageRules(); assertEquals(1, rulesFromStorage.size()); assertEquals(Integer.parseInt((String)rulesFromStorage.get(0).get("ruleid")), rid); // delete rule replay(routingService); firewall.deleteRule(rid); verify(routingService); test_changes.add(Masked.of(AppCookie.makeCookie(APP_ID, rule.ruleid), singleRuleMask)); rulesFromStorage = firewall.getStorageRules(); assertEquals(0, rulesFromStorage.size()); assertTrue(compareU64ListsOrdered(wc1.getValue(),test_changes)); reset(routingService); } @Test public void testFirewallDisabled() throws Exception { // firewall isn't enabled by default // so, it shouldn't make any decision // add TCP rule FirewallRule rule = new FirewallRule(); rule.nw_proto = IpProtocol.TCP; rule.any_nw_proto = false; rule.priority = 1; firewall.addRule(rule); this.setPacketIn(tcpPacket); firewall.receive(sw, this.packetIn, cntx); verify(sw); assertEquals(1, firewall.rules.size()); IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); assertNull(decision); } @Test public void testSimpleAllowRule() throws Exception { // enable firewall first firewall.enableFirewall(true); // add TCP rule FirewallRule rule = new FirewallRule(); rule.dl_type = EthType.IPv4; rule.any_dl_type = false; rule.nw_proto = IpProtocol.TCP; rule.any_nw_proto = false; // source is IP 192.168.1.2 rule.nw_src_prefix_and_mask = IPv4AddressWithMask.of("192.168.1.2/32"); rule.any_nw_src = false; // dest is network 192.168.1.0/24 rule.nw_dst_prefix_and_mask = IPv4AddressWithMask.of("192.168.1.0/24"); rule.any_nw_dst = false; rule.priority = 1; firewall.addRule(rule); U64 TCP_COOKIE = AppCookie.makeCookie(APP_ID, rule.ruleid); // simulate a packet-in events this.setPacketIn(tcpPacketReply); firewall.receive(sw, this.packetIn, cntx); verify(sw); IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); assertEquals(IRoutingDecision.RoutingAction.FORWARD_OR_FLOOD, decision.getRoutingAction()); assertEquals(TCP_COOKIE, decision.getDescriptor()); // clear decision IRoutingDecision.rtStore.remove(cntx, IRoutingDecision.CONTEXT_DECISION); this.setPacketIn(tcpPacket); firewall.receive(sw, this.packetIn, cntx); verify(sw); decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); assertEquals(IRoutingDecision.RoutingAction.DROP, decision.getRoutingAction()); assertEquals(RULE_MISS_COOKIE, decision.getDescriptor()); } @Test public void testOverlappingRules() throws Exception { firewall.enableFirewall(true); // add TCP port 80 (destination only) allow rule FirewallRule rule = new FirewallRule(); rule.dl_type = EthType.IPv4; rule.any_dl_type = false; rule.nw_proto = IpProtocol.TCP; rule.any_nw_proto = false; rule.tp_dst = TransportPort.of(80); rule.priority = 1; firewall.addRule(rule); U64 TCP_COOKIE = AppCookie.makeCookie(APP_ID, rule.ruleid); // add block all rule rule = new FirewallRule(); rule.action = FirewallRule.FirewallAction.DROP; rule.priority = 2; firewall.addRule(rule); U64 BLOCK_ALL_COOKIE = AppCookie.makeCookie(APP_ID, rule.ruleid); assertEquals(2, firewall.rules.size()); // packet destined to TCP port 80 - should be allowed this.setPacketIn(tcpPacket); firewall.receive(sw, this.packetIn, cntx); verify(sw); IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.FORWARD_OR_FLOOD); assertEquals(TCP_COOKIE, decision.getDescriptor()); // clear decision IRoutingDecision.rtStore.remove(cntx, IRoutingDecision.CONTEXT_DECISION); // packet destined for port 81 - should be denied this.setPacketIn(tcpPacketReply); firewall.receive(sw, this.packetIn, cntx); verify(sw); decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.DROP); assertEquals(BLOCK_ALL_COOKIE, decision.getDescriptor()); } @Test public void testARP() throws Exception { // enable firewall first firewall.enableFirewall(true); // no rules inserted so all traffic other than broadcast and ARP-request-broadcast should be blocked // simulate an ARP broadcast packet-in event this.setPacketIn(broadcastARPPacket); firewall.receive(sw, this.packetIn, cntx); verify(sw); // broadcast-ARP traffic should be allowed IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); assertEquals(IRoutingDecision.RoutingAction.MULTICAST, decision.getRoutingAction()); assertEquals(ALLOW_BCAST_COOKIE, decision.getDescriptor()); // clear decision IRoutingDecision.rtStore.remove(cntx, IRoutingDecision.CONTEXT_DECISION); // simulate an ARP reply packet-in event this.setPacketIn(ARPReplyPacket); firewall.receive(sw, this.packetIn, cntx); verify(sw); // ARP reply traffic should be denied decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.DROP); assertEquals(RULE_MISS_COOKIE, decision.getDescriptor()); } @Test public void testIPBroadcast() throws Exception { // enable firewall first firewall.enableFirewall(true); // set subnet mask for IP broadcast firewall.setSubnetMask("255.255.255.0"); // no rules inserted so all traffic other than broadcast and ARP-request-broadcast should be blocked // simulate a packet-in event this.setPacketIn(broadcastIPPacket); firewall.receive(sw, this.packetIn, cntx); verify(sw); // broadcast traffic should be allowed IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); assertEquals(IRoutingDecision.RoutingAction.MULTICAST, decision.getRoutingAction()); assertEquals(ALLOW_BCAST_COOKIE, decision.getDescriptor()); } @Test public void testMalformedIPBroadcast() throws Exception { // enable firewall first firewall.enableFirewall(true); // no rules inserted so all traffic other than broadcast and ARP-request-broadcast should be blocked // simulate a packet-in event this.setPacketIn(broadcastMalformedPacket); firewall.receive(sw, this.packetIn, cntx); verify(sw); // malformed broadcast traffic should NOT be allowed IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.DROP); assertEquals(DENY_BCAST_COOKIE, decision.getDescriptor()); } @Test public void testLayer2Rule() throws Exception { // enable firewall first firewall.enableFirewall(true); // add L2 rule FirewallRule rule = new FirewallRule(); rule.dl_src = MacAddress.of("00:44:33:22:11:00"); rule.any_dl_src = false; rule.dl_dst = MacAddress.of("00:11:22:33:44:55"); rule.any_dl_dst = false; rule.priority = 1; firewall.addRule(rule); U64 L2_LAYER_COOKIE = AppCookie.makeCookie(APP_ID, rule.ruleid); // add TCP deny all rule rule = new FirewallRule(); rule.nw_proto = IpProtocol.TCP; rule.any_nw_proto = false; rule.priority = 2; rule.action = FirewallRule.FirewallAction.DROP; firewall.addRule(rule); // simulate a packet-in event this.setPacketIn(tcpPacket); firewall.receive(sw, this.packetIn, cntx); verify(sw); IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.FORWARD_OR_FLOOD); assertEquals(L2_LAYER_COOKIE, decision.getDescriptor()); } @Test public void testDuplicateLayer2Rule() { FirewallRule rule1 = new FirewallRule(); rule1.dl_src = MacAddress.of("00:44:33:22:11:00"); rule1.any_dl_src = false; rule1.dl_dst = MacAddress.of("00:11:22:33:44:55"); rule1.any_dl_dst = false; rule1.any_dpid = false; rule1.dpid = DatapathId.of(0x0102030405060708L); rule1.any_in_port = false; rule1.in_port = OFPort.LOCAL; rule1.priority = 1; rule1.ruleid = rule1.genID(); // Rule same as itself. assertTrue(rule1.isSameAs(rule1)); FirewallRule rule2 = new FirewallRule(); rule2.dl_src = MacAddress.of("00:44:33:22:11:00"); rule2.any_dl_src = false; rule2.dl_dst = MacAddress.of("00:11:22:33:44:55"); rule2.any_dl_dst = false; rule2.any_dpid = false; rule2.dpid = DatapathId.of(0x0102030405060708L); rule2.any_in_port = false; rule2.in_port = OFPort.LOCAL; rule2.priority = 1; rule2.ruleid = rule2.genID(); // Separate object instances, but otherwise identical rule. assertTrue(rule1.isSameAs(rule2)); // Change dl_src, rules no longer "same" MacAddress tmp = rule2.dl_src; rule2.dl_src = MacAddress.of("08:01:02:03:04:05"); rule2.ruleid = rule2.genID(); assertFalse(rule1.isSameAs(rule2)); // Restore dl_src, rules should be "same" again rule2.dl_src = tmp; rule2.ruleid = rule2.genID(); assertTrue(rule1.isSameAs(rule2)); // Change dl_dst, rules no longer "same" rule2.dl_dst = MacAddress.of("00:01:02:03:04:05"); assertFalse(rule1.isSameAs(rule2)); } /* Testing to make sure that the cookies are properly formatted with the correct info before hitting the firewall. */ @Test public void cookieAddedSuccessfully() { assertEquals("DENY_BCAST_COOKIE app_id is not correct", APP_ID, AppCookie.extractApp(DENY_BCAST_COOKIE)); assertEquals("DENY_BCAST_COOKIE user_id is not correct", 0xaaaaaaL, AppCookie.extractUser(DENY_BCAST_COOKIE)); assertEquals("ALLOW_BCAST_COOKIE app_id is not correct", APP_ID, AppCookie.extractApp(DENY_BCAST_COOKIE)); assertEquals("ALLOW_BCAST_COOKIE user_id is not correct", 0x555555L, AppCookie.extractUser(ALLOW_BCAST_COOKIE)); assertEquals("RULE_MISS_COOKIE app_id is not correct", APP_ID, AppCookie.extractApp(DENY_BCAST_COOKIE)); assertEquals("RULE_MISS_COOKIE user_id is not correct", 0xffffffL, AppCookie.extractUser(RULE_MISS_COOKIE)); } }