From a2bffd829b472164288b07785244c8ffd74872ae Mon Sep 17 00:00:00 2001
From: Alex Reimers <alex@bigswitch.com>
Date: Wed, 29 Aug 2012 17:13:04 -0700
Subject: [PATCH] FL-82 - Firewall.java - Protect the firewall rules with
 synchronization.

---
 .../firewall/Firewall.java                    | 63 +++++++------------
 .../firewall/FirewallTest.java                | 10 +--
 2 files changed, 28 insertions(+), 45 deletions(-)

diff --git a/src/main/java/net/floodlightcontroller/firewall/Firewall.java b/src/main/java/net/floodlightcontroller/firewall/Firewall.java
index a1335a51b..5a270430a 100644
--- a/src/main/java/net/floodlightcontroller/firewall/Firewall.java
+++ b/src/main/java/net/floodlightcontroller/firewall/Firewall.java
@@ -40,7 +40,7 @@ public class Firewall implements IFirewallService, IOFMessageListener, IFloodlig
     protected IStorageSourceService storageSource;
     protected IRestApiService restApi;
     protected static Logger logger;
-    protected ArrayList<FirewallRule> rules;
+    protected List<FirewallRule> rules; // protected by synchornized
     protected boolean enabled;
     protected int subnet_mask = IPv4.toIPv4Address("255.255.255.0");
 
@@ -119,19 +119,7 @@ public class Firewall implements IFirewallService, IOFMessageListener, IFloodlig
         l.add(IRestApiService.class);
         return l;
     }
-
-    public IFloodlightProviderService getFloodlightProvider() {
-        return floodlightProvider;
-    }
-
-    public void setFloodlightProvider(IFloodlightProviderService floodlightProvider) {
-        this.floodlightProvider = floodlightProvider;
-    }
-
-    public void setStorageSource(IStorageSourceService storageSource) {
-        this.storageSource = storageSource;
-    }
-
+    
     /**
      * Reads the rules from the storage and creates a sorted arraylist of FirewallRule
      * from them.
@@ -223,14 +211,6 @@ public class Firewall implements IFirewallService, IOFMessageListener, IFloodlig
         return l;
     }
 
-    /**
-     * used for debugging and unittests
-     * @return the number of rules
-     */
-    public int countRules() {
-        return this.rules.size();
-    }
-
     @Override
     public void init(FloodlightModuleContext context)
             throws FloodlightModuleException {
@@ -254,12 +234,14 @@ public class Firewall implements IFirewallService, IOFMessageListener, IFloodlig
         // storage, create table and read rules
         storageSource.createTable(TABLE_NAME, null);
         storageSource.setTablePrimaryKeyName(TABLE_NAME, COLUMN_RULEID);
-        this.rules = readRulesFromStorage();
+        synchronized (rules) {
+            this.rules = readRulesFromStorage();
+        }
     }
 
     @Override
     public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
-        if (this.enabled == false) return Command.CONTINUE;
+        if (!this.enabled) return Command.CONTINUE;
 
         switch (msg.getType()) {
             case PACKET_IN:
@@ -284,7 +266,7 @@ public class Firewall implements IFirewallService, IOFMessageListener, IFloodlig
     public void enableFirewall() {
         // check if the firewall module is not listening for events, if not, then start listening (enable it)
         List<IOFMessageListener> listeners = floodlightProvider.getListeners().get(OFType.PACKET_IN);
-        if (listeners != null && listeners.contains(this) == false) {
+        if ((listeners != null) && (!listeners.contains(this))) {
             // enable firewall, i.e. listen for packet-in events
             floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
         }
@@ -295,7 +277,7 @@ public class Firewall implements IFirewallService, IOFMessageListener, IFloodlig
     public void disableFirewall() {
         // check if the firewall module is listening for events, if yes, then remove it from listeners (disable it)
         List<IOFMessageListener> listeners = floodlightProvider.getListeners().get(OFType.PACKET_IN);
-        if (listeners != null && listeners.contains(this) == true) {
+        if ((listeners != null) && (listeners.contains(this))) {
             // disable firewall, i.e. stop listening for packet-in events
             floodlightProvider.removeOFMessageListener(OFType.PACKET_IN, this);
         }
@@ -336,7 +318,7 @@ public class Firewall implements IFirewallService, IOFMessageListener, IFloodlig
     }
 
     @Override
-    public void addRule(FirewallRule rule) {
+    public synchronized void addRule(FirewallRule rule) {
         rule.ruleid = rule.genID();
         int i = 0;
         // locate the position of the new rule in the sorted arraylist
@@ -376,7 +358,7 @@ public class Firewall implements IFirewallService, IOFMessageListener, IFloodlig
     }
 
     @Override
-    public void deleteRule(int ruleid) {
+    public synchronized void deleteRule(int ruleid) {
         Iterator<FirewallRule> iter = this.rules.iterator();
         while (iter.hasNext()) {
             FirewallRule r = iter.next();
@@ -419,18 +401,19 @@ public class Firewall implements IFirewallService, IOFMessageListener, IFloodlig
         Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
         WildcardsPair wildcards = new WildcardsPair();
 
-        Iterator<FirewallRule> iter = this.rules.iterator();
-
-        FirewallRule rule = null;
-        // iterate through list to find a matching firewall rule
-        while (iter.hasNext()) {
-            // get next rule from list
-            rule = iter.next();
-
-            // check if rule matches
-            if (rule.matchesFlow(sw.getId(), pi.getInPort(), eth, wildcards) == true) {
-                matched_rule = rule;
-                break;
+        synchronized (rules) {
+            Iterator<FirewallRule> iter = this.rules.iterator();
+            FirewallRule rule = null;
+            // iterate through list to find a matching firewall rule
+            while (iter.hasNext()) {
+                // get next rule from list
+                rule = iter.next();
+    
+                // check if rule matches
+                if (rule.matchesFlow(sw.getId(), pi.getInPort(), eth, wildcards) == true) {
+                    matched_rule = rule;
+                    break;
+                }
             }
         }
 
diff --git a/src/test/java/net/floodlightcontroller/firewall/FirewallTest.java b/src/test/java/net/floodlightcontroller/firewall/FirewallTest.java
index 532da8fd8..2919d4eb7 100644
--- a/src/test/java/net/floodlightcontroller/firewall/FirewallTest.java
+++ b/src/test/java/net/floodlightcontroller/firewall/FirewallTest.java
@@ -215,7 +215,7 @@ public class FirewallTest extends FloodlightTestCase {
         firewall.receive(sw, this.packetIn, cntx);
         verify(sw);
 
-        assertEquals(0, firewall.countRules());
+        assertEquals(0, firewall.rules.size());
 
         IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
         // no rules to match, so firewall should deny
@@ -272,7 +272,7 @@ public class FirewallTest extends FloodlightTestCase {
         firewall.receive(sw, this.packetIn, cntx);
         verify(sw);
 
-        assertEquals(1, firewall.countRules());
+        assertEquals(1, firewall.rules.size());
 
         IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
         assertNull(decision);
@@ -335,7 +335,7 @@ public class FirewallTest extends FloodlightTestCase {
         rule.priority = 2;
         firewall.addRule(rule);
 
-        assertEquals(2, firewall.countRules());
+        assertEquals(2, firewall.rules.size());
 
         // packet destined to TCP port 80 - should be allowed
 
@@ -374,7 +374,7 @@ public class FirewallTest extends FloodlightTestCase {
 
         // broadcast-ARP traffic should be allowed
         IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
-        assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.FORWARD_OR_FLOOD);
+        assertEquals(IRoutingDecision.RoutingAction.MULTICAST, decision.getRoutingAction());
         
         // clear decision
         IRoutingDecision.rtStore.remove(cntx, IRoutingDecision.CONTEXT_DECISION);
@@ -408,7 +408,7 @@ public class FirewallTest extends FloodlightTestCase {
 
         // broadcast traffic should be allowed
         IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
-        assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.FORWARD_OR_FLOOD);
+        assertEquals(IRoutingDecision.RoutingAction.MULTICAST, decision.getRoutingAction());
     }
 
     @Test
-- 
GitLab