From e4a099fcb8667f146b46e0fe60a1c1d747f02ce0 Mon Sep 17 00:00:00 2001
From: Pengfei Lu <1990.lpf@gmail.com>
Date: Wed, 8 Jul 2015 20:23:56 +0800
Subject: [PATCH] Refactoring ACL.java and IACLService.java

- fix bug in processing allowing ACL rule
- update Javadoc
---
 .../accesscontrollist/ACL.java                | 379 ++++++++++--------
 .../accesscontrollist/IACLService.java        |  98 +++--
 2 files changed, 258 insertions(+), 219 deletions(-)

diff --git a/src/main/java/net/floodlightcontroller/accesscontrollist/ACL.java b/src/main/java/net/floodlightcontroller/accesscontrollist/ACL.java
index 1c87956f5..b3c2a88f9 100644
--- a/src/main/java/net/floodlightcontroller/accesscontrollist/ACL.java
+++ b/src/main/java/net/floodlightcontroller/accesscontrollist/ACL.java
@@ -24,10 +24,10 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
 
 import net.floodlightcontroller.accesscontrollist.ACLRule.Action;
 import net.floodlightcontroller.accesscontrollist.ap.AP;
@@ -54,226 +54,254 @@ import org.slf4j.LoggerFactory;
 
 public class ACL implements IACLService, IFloodlightModule, IDeviceListener {
 
-	// service modules needed
 	protected IRestApiService restApi;
 	protected IDeviceService deviceManager;
 	protected IStorageSourceService storageSource;
 	protected static Logger logger;
-	
-	private APManager apManager;
 
-	// variable used
+	private APManager apManager;
 	private int lastRuleId = 1; // rule id counter
-	private List<ACLRule> ruleSet;
+	private Map<Integer, ACLRule> aclRules;
 	private Map<String, Integer> dpid2FlowPriority;
 	private Map<Integer, Set<String>> ruleId2Dpid;
 	private Map<Integer, Set<String>> ruleId2FlowName;
+	private Map<Integer, List<Integer>> deny2Allow;
+
+	private final int DEFAULT_PRIORITY = 30000;
+
+	/**
+	 * Checks if an existing ACL rule already works in a given switch.
+	 */
+	private boolean checkIfRuleWorksInSwitch(int ruleId, String dpid) {
+		return ruleId2Dpid.containsKey(ruleId)
+				&& ruleId2Dpid.get(ruleId).contains(dpid);
+	}
+
+	/**
+	 * Adds a new mapping from ACL rule to ACL flow.
+	 */
+	private void addRuleToFlowMapping(int ruleId, String flowName) {
+		if (!ruleId2FlowName.containsKey(ruleId)) {
+			ruleId2FlowName.put(ruleId, new HashSet<String>());
+		}
+		ruleId2FlowName.get(ruleId).add(flowName);
+	}
+
+	/**
+	 * Adds a new mapping from ACL rule to switch.
+	 */
+	private void addRuleToSwitchMapping(int ruleId, String dpid) {
+		if (!ruleId2Dpid.containsKey(ruleId)) {
+			ruleId2Dpid.put(ruleId, new HashSet<String>());
+		}
+		ruleId2Dpid.get(ruleId).add(dpid);
+	}
 
 	/**
-	 * used by REST API to query ACL rules
+	 * Gets the current priority for new ACL flow by device id.
 	 */
+	private int getPriorityBySwitch(String dpid) {
+		if (!dpid2FlowPriority.containsKey(dpid)) {
+			dpid2FlowPriority.put(dpid, DEFAULT_PRIORITY - 1);
+			return DEFAULT_PRIORITY;
+		} else {
+			int priority = dpid2FlowPriority.get(dpid);
+			dpid2FlowPriority.put(dpid, priority - 1);
+			return priority;
+		}
+	}
+
 	@Override
 	public List<ACLRule> getRules() {
-		return this.ruleSet;
+		return new ArrayList<ACLRule>(aclRules.values());
 	}
 
 	/**
-	 * check if the new rule matches an existing rule
+	 * Checks if the new ACL rule matches an existing rule. If existing allowing
+	 * rules matches the new denying rule, store the mappings.
+	 * 
+	 * @return true if the new ACL rule matches an existing rule, false
+	 *         otherwise
 	 */
 	private boolean checkRuleMatch(ACLRule newRule) {
-		Iterator<ACLRule> iter = ruleSet.iterator();
-		while (iter.hasNext()) {
-			ACLRule existingRule = iter.next();
-			if(newRule.match(existingRule)){
-				logger.error("existing rule: " + existingRule);
+		List<Integer> allowRuleList = new ArrayList<>();
+		for (ACLRule existingRule : getRules()) {
+			if (newRule.match(existingRule)) {
 				return true;
 			}
+
+			if (existingRule.getAction() == Action.ALLOW
+					&& newRule.getAction() == Action.DENY) {
+				if (existingRule.match(newRule)) {
+					allowRuleList.add(existingRule.getId());
+				}
+			}
 		}
+		deny2Allow.put(newRule.getId(), allowRuleList);
 		return false;
 	}
-	
-	/**
-	 * used by REST API to add ACL rule
-	 * @return if the new ACL rule is added successfully
-	 */
+
 	@Override
 	public boolean addRule(ACLRule rule) {
-
-		if(checkRuleMatch(rule)){
+		rule.setId(lastRuleId++);
+		if (checkRuleMatch(rule)) {
+			lastRuleId--;
 			return false;
 		}
-		
-		rule.setId(lastRuleId++);
-		this.ruleSet.add(rule);
-		logger.info("No.{} ACL rule added.", rule.getId());
-		enforceAddedRule(rule);
+		aclRules.put(rule.getId(), rule);
+		logger.info("ACL rule(id:{}) is added.", rule.getId());
+		if (rule.getAction() != Action.ALLOW) {
+			enforceAddedRule(rule);
+		}
 		return true;
 	}
 
-	/**
-	 * used by REST API to remove ACL rule
-	 */
 	@Override
-	public void removeRule(int ruleid) {
-
-		Iterator<ACLRule> iter = this.ruleSet.iterator();
-		while (iter.hasNext()) {
-			ACLRule rule = iter.next();
-			if (rule.getId() == ruleid) {
				iter.remove();
-				break;
-			}
-		}
-
-		logger.info("No.{} ACL rule removed.", ruleid);
-		enforceRemovedRule(ruleid);
+	public void removeRule(int ruleId) {
+		aclRules.remove(ruleId);
+		logger.info("ACL rule(id:{}) is removed.", ruleId);
+		enforceRemovedRule(ruleId);
 	}
 
-	/**
-	 * used by REST API to clear ACL
-	 */
 	@Override
 	public void removeAllRules() {
-		
 		this.lastRuleId = 1;
-		this.ruleSet = new ArrayList<ACLRule>();
-		this.dpid2FlowPriority = new HashMap<String, Integer>();
-		this.ruleId2Dpid = new HashMap<Integer, Set<String>>();
-
-		Iterator<Integer> ruleIdIter = ruleId2FlowName.keySet().iterator();
-		while (ruleIdIter.hasNext()) {
-			int ruleId = ruleIdIter.next();
-			Set<String> flowNameSet = ruleId2FlowName.get(ruleId);
-			logger.debug("No.{} ACL rule removed.", ruleId);
+		this.aclRules = new TreeMap<>();
+		this.dpid2FlowPriority = new HashMap<>();
+		this.ruleId2Dpid = new HashMap<>();
+		this.deny2Allow = new HashMap<>();
+
+		for (Set<String> flowNameSet : ruleId2FlowName.values()) {
 			for (String flowName : flowNameSet) {
-				removeFlow(flowName);
-				logger.debug("ACL flow {} removed.", flowName);
+				storageSource.deleteRowAsync("controller_staticflowtableentry",
+						flowName);
+				logger.debug("ACL flow(id:{}) is removed.", flowName);
 			}
 		}
-		this.ruleId2FlowName = new HashMap<Integer, Set<String>>();
+		this.ruleId2FlowName = new HashMap<>();
 	}
 
 	/**
-	 * enforce new added rule
+	 * Enforces denying ACL rule by ACL flow.
 	 */
-	private void enforceAddedRule(ACLRule rule) {
-
+	private void enforceAddedRule(ACLRule denyRule) {
 		Set<String> dpidSet;
-		if (rule.getNw_src() != null) {
-			dpidSet = apManager.getDpidSet(rule.getNw_src_prefix(),rule.getNw_src_maskbits());
+		if (denyRule.getNw_src() != null) {
+			dpidSet = apManager.getDpidSet(denyRule.getNw_src_prefix(),
+					denyRule.getNw_src_maskbits());
 		} else {
-			dpidSet = apManager.getDpidSet(rule.getNw_dst_prefix(),rule.getNw_dst_maskbits());
+			dpidSet = apManager.getDpidSet(denyRule.getNw_dst_prefix(),
+					denyRule.getNw_dst_maskbits());
 		}
 
-		Iterator<String> dpidIter = dpidSet.iterator();
-		Set<String> nameSet = new HashSet<String>();
-
-		while (dpidIter.hasNext()) {
-			String dpid = dpidIter.next();
-			String flowName = "ACLRule_" + rule.getId() + "_" + dpid;
-			generateFlow(rule, dpid, flowName);
-			nameSet.add(flowName);
+		for (String dpid : dpidSet) {
+			String flowName;
+			List<Integer> allowRuleList = deny2Allow.get(denyRule.getId());
+			for (int allowRuleId : allowRuleList) {
+				flowName = "ACLRule_" + allowRuleId + "_" + dpid;
+				generateFlow(aclRules.get(allowRuleId), dpid, flowName);
+			}
+			flowName = "ACLRule_" + denyRule.getId() + "_" + dpid;
+			generateFlow(denyRule, dpid, flowName);
 		}
-		ruleId2FlowName.put(rule.getId(), nameSet);
-		ruleId2Dpid.put(rule.getId(), dpidSet);
 	}
 
 	/**
-	 * enforce removed rule
+	 * Enforces removing an existing ACL rule.
 	 */
 	private void enforceRemovedRule(int ruleId) {
-
-		Set<String> flowEntryName = ruleId2FlowName.get(ruleId);
-		Iterator<String> iter = flowEntryName.iterator();
-		while (iter.hasNext()) {
-			String name = iter.next();
-			removeFlow(name);
-			logger.debug("ACL flow " + name + " removed.");
+		if (ruleId2FlowName.containsKey(ruleId)) {
+			for (String flowName : ruleId2FlowName.get(ruleId)) {
+				storageSource.deleteRowAsync("controller_staticflowtableentry",
+						flowName);
+				logger.debug("ACL flow(id:{}) is removed.", flowName);
+			}
+			ruleId2FlowName.remove(ruleId);
 		}
-
+		ruleId2Dpid.remove(ruleId);
+		deny2Allow.remove(ruleId);
 	}
-		
+
 	/**
-	 * generate and push ACL flow entry
+	 * Generates ACL flow rule according to ACL rule 
+	 * and installs it into switch.
 	 */
 	private void generateFlow(ACLRule rule, String dpid, String flowName) {
-
-		int priority;
-		// get priority for the new flow entry
-		if (dpid2FlowPriority.get(dpid) == null) {
-			dpid2FlowPriority.put(dpid, 30000);
-			priority = 30000;
-		} else {
-			priority = dpid2FlowPriority.get(dpid);
+		if (rule == null || checkIfRuleWorksInSwitch(rule.getId(), dpid)) {
+			return;
 		}
 
+		int priority = getPriorityBySwitch(dpid);
 		if (rule.getNw_src() != null) {
-			
-			HashMap<String,Object> flow = new HashMap<String,Object>();
-	        
+
+			HashMap<String, Object> flow = new HashMap<String, Object>();
+
 			flow.put(StaticFlowEntryPusher.COLUMN_SWITCH, dpid);
 			flow.put(StaticFlowEntryPusher.COLUMN_NAME, flowName);
-			flow.put(StaticFlowEntryPusher.COLUMN_ACTIVE, Boolean.toString(true));
+			flow.put(StaticFlowEntryPusher.COLUMN_ACTIVE,
+					Boolean.toString(true));
 			flow.put(StaticFlowEntryPusher.COLUMN_COOKIE, "0");
-			flow.put(StaticFlowEntryPusher.COLUMN_PRIORITY, Integer.toString(priority));
-			dpid2FlowPriority.put(dpid, --priority);
-			
-			
+			flow.put(StaticFlowEntryPusher.COLUMN_PRIORITY,
+					Integer.toString(priority));
+
 			flow.put(StaticFlowEntryPusher.COLUMN_DL_TYPE, "2048");
 			flow.put(StaticFlowEntryPusher.COLUMN_NW_SRC, rule.getNw_src());
-			
-			// process for the nw_dst attribute
+
 			if (rule.getNw_dst() != null) {
 				flow.put(StaticFlowEntryPusher.COLUMN_NW_DST, rule.getNw_dst());
 			}
 			if (rule.getNw_proto() != 0) {
-				flow.put(StaticFlowEntryPusher.COLUMN_NW_PROTO, Integer.toString(rule.getNw_proto()));
+				flow.put(StaticFlowEntryPusher.COLUMN_NW_PROTO,
+						Integer.toString(rule.getNw_proto()));
 			}
 			if (rule.getAction() == Action.ALLOW) {
-				flow.put(StaticFlowEntryPusher.COLUMN_ACTIONS, "output=controller");
+				flow.put(StaticFlowEntryPusher.COLUMN_ACTIONS,
+						"output=controller");
 			}
 			if (rule.getTp_dst() != 0) {
-				flow.put(StaticFlowEntryPusher.COLUMN_TP_DST, Integer.toString(rule.getTp_dst()));
+				flow.put(StaticFlowEntryPusher.COLUMN_TP_DST,
+						Integer.toString(rule.getTp_dst()));
 			}
-	        
-	        storageSource.insertRowAsync(StaticFlowEntryPusher.TABLE_NAME, flow);
-			
+
+			storageSource
+					.insertRowAsync(StaticFlowEntryPusher.TABLE_NAME, flow);
+
 		} else {
-			
-			HashMap<String,Object> flow = new HashMap<String,Object>();
-	        
+
+			HashMap<String, Object> flow = new HashMap<String, Object>();
+
 			flow.put(StaticFlowEntryPusher.COLUMN_SWITCH, dpid);
 			flow.put(StaticFlowEntryPusher.COLUMN_NAME, flowName);
-			flow.put(StaticFlowEntryPusher.COLUMN_ACTIVE, Boolean.toString(true));
+			flow.put(StaticFlowEntryPusher.COLUMN_ACTIVE,
+					Boolean.toString(true));
 			flow.put(StaticFlowEntryPusher.COLUMN_COOKIE, "0");
-			flow.put(StaticFlowEntryPusher.COLUMN_PRIORITY, Integer.toString(priority));
-			dpid2FlowPriority.put(dpid, --priority);
-			
+			flow.put(StaticFlowEntryPusher.COLUMN_PRIORITY,
+					Integer.toString(priority));
+
 			flow.put(StaticFlowEntryPusher.COLUMN_DL_TYPE, "2048");
 			flow.put(StaticFlowEntryPusher.COLUMN_NW_DST, rule.getNw_dst());
 
 			if (rule.getNw_proto() != 0) {
-				flow.put(StaticFlowEntryPusher.COLUMN_NW_PROTO, Integer.toString(rule.getNw_proto()));
+				flow.put(StaticFlowEntryPusher.COLUMN_NW_PROTO,
+						Integer.toString(rule.getNw_proto()));
 			}
 			if (rule.getAction() == Action.ALLOW) {
-				flow.put(StaticFlowEntryPusher.COLUMN_ACTIONS, "output=controller");
+				flow.put(StaticFlowEntryPusher.COLUMN_ACTIONS,
+						"output=controller");
 			}
 			if (rule.getTp_dst() != 0) {
-				flow.put(StaticFlowEntryPusher.COLUMN_TP_DST, Integer.toString(rule.getTp_dst()));
+				flow.put(StaticFlowEntryPusher.COLUMN_TP_DST,
+						Integer.toString(rule.getTp_dst()));
 			}
-	        
-	        storageSource.insertRowAsync(StaticFlowEntryPusher.TABLE_NAME, flow);
-	        
-		}
-		logger.info("ACL flow " + flowName + " added in " + dpid);
-	}
 
-	/**
-	 * remove ACL flow entry
-	 */
-	private void removeFlow(String name) {
-		storageSource.deleteRowAsync("controller_staticflowtableentry", name);
-	}
+			storageSource
+					.insertRowAsync(StaticFlowEntryPusher.TABLE_NAME, flow);
 
+		}
+		addRuleToSwitchMapping(rule.getId(), dpid);
+		addRuleToFlowMapping(rule.getId(), flowName);
+		logger.debug("ACL flow(id:{}) is added in {}.", flowName, dpid);
+	}
 
 	@Override
 	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
@@ -306,11 +334,12 @@ public class ACL implements IACLService, IFloodlightModule, IDeviceListener {
 		logger = LoggerFactory.getLogger(ACL.class);
 		storageSource = context.getServiceImpl(IStorageSourceService.class);
 
-		ruleSet = new ArrayList<ACLRule>();
+		aclRules = new TreeMap<>();
 		apManager = new APManager();
-		ruleId2FlowName = new HashMap<Integer, Set<String>>();
-		ruleId2Dpid =  new HashMap<Integer, Set<String>>();
-		dpid2FlowPriority = new HashMap<String, Integer>();
+		ruleId2FlowName = new HashMap<>();
+		ruleId2Dpid = new HashMap<>();
+		dpid2FlowPriority = new HashMap<>();
+		deny2Allow = new HashMap<>();
 	}
 
 	@Override
@@ -320,60 +349,55 @@ public class ACL implements IACLService, IFloodlightModule, IDeviceListener {
 		deviceManager.addListener(this);
 	}
 
-	/**
-	 * listen for new device
-	 */
 	@Override
 	public void deviceAdded(IDevice device) {
 		SwitchPort[] switchPort = device.getAttachmentPoints();
 		IPv4Address[] ips = device.getIPv4Addresses();
-		if(ips.length == 0){
+		if (ips.length == 0) {
 			// A new no-ip device added
 			return;
 		}
-		String dpid = HexString.toHexString(switchPort[0].getSwitchDPID().getLong());
+
+		String dpid = HexString.toHexString(switchPort[0].getSwitchDPID()
+				.getLong());
 		String ip = IPv4.fromIPv4Address(ips[0].getInt());
-		logger.debug("New AP added. [dpid:" + dpid + " ip:" + ip + "]");
+		logger.debug("AP(dpid:{},ip:{}) is added", dpid, ip);
 
-		AP ap = new AP(ip,dpid);
+		AP ap = new AP(ip, dpid);
 		apManager.addAP(ap);
 		processAPAdded(ap);
 	}
 
 	/**
-	 * push ACL flow given the new device
+	 * Generates new ACL flow when a new device appears
+	 * and existing ACL rules denies its traffic.
 	 */
 	private void processAPAdded(AP ap) {
-
 		String dpid = ap.getDpid();
 		int ip = IPv4.toIPv4Address(ap.getIp());
 
-		Iterator<ACLRule> iter = this.ruleSet.iterator();
-		while (iter.hasNext()) {
-			ACLRule rule = iter.next();
-			if (rule.getNw_src() != null) {
-				if (IPAddressUtil.containIP(rule.getNw_src_prefix(),
-						rule.getNw_src_maskbits(), ip)) {
-					// check if there is a flow entry in the switch for the rule
-					if (ruleId2Dpid.get(rule.getId()).contains(dpid)) {
-						continue;
+		for (ACLRule rule : getRules()) {
+			if (rule.getAction() != Action.ALLOW) {
+				if (rule.getNw_src() != null) {
+					if (IPAddressUtil.containIP(rule.getNw_src_prefix(),
+							rule.getNw_src_maskbits(), ip)) {
+						if (checkIfRuleWorksInSwitch(rule.getId(), dpid)) {
+							continue;
+						}
+						String flowName = "ACLRule_" + rule.getId() + "_"
+								+ dpid;
+						generateFlow(rule, dpid, flowName);
 					}
-					String flowName = "ACLRule_" + rule.getId() + "_" + dpid;
-					ruleId2FlowName.get(rule.getId()).add(flowName);
-					ruleId2Dpid.get(rule.getId()).add(dpid);
-					generateFlow(rule, dpid, flowName);
-				}
-			} else {
-				if (IPAddressUtil.containIP(rule.getNw_dst_prefix(),
-						rule.getNw_dst_maskbits(), ip)) {
-					// check if there is a flow entry in the switch for the rule
-					if (ruleId2Dpid.get(rule.getId()).contains(dpid)) {
-						continue;
+				} else {
+					if (IPAddressUtil.containIP(rule.getNw_dst_prefix(),
+							rule.getNw_dst_maskbits(), ip)) {
+						if (checkIfRuleWorksInSwitch(rule.getId(), dpid)) {
+							continue;
+						}
+						String flowName = "ACLRule_" + rule.getId() + "_"
+								+ dpid;
+						generateFlow(rule, dpid, flowName);
 					}
-					String flowName = "ACLRule_" + rule.getId() + "_" + dpid;
-					ruleId2FlowName.get(rule.getId()).add(flowName);
-					ruleId2Dpid.get(rule.getId()).add(dpid);
-					generateFlow(rule, dpid, flowName);
 				}
 			}
 		}
@@ -391,22 +415,23 @@ public class ACL implements IACLService, IFloodlightModule, IDeviceListener {
 
 	@Override
 	public void deviceIPV4AddrChanged(IDevice device) {
-		
+
 		SwitchPort[] switchPort = device.getAttachmentPoints();
 		IPv4Address[] ips = device.getIPv4Addresses();
-		
-		String dpid = HexString.toHexString(switchPort[0].getSwitchDPID().getLong());
+
+		String dpid = HexString.toHexString(switchPort[0].getSwitchDPID()
+				.getLong());
 		String ip = null;
-		
-		// some device may first appear with no IP address(default set to 0.0.0.0), ignore it
-		for(IPv4Address i : ips){
-			if(i.getInt() != 0){
+		// some device may first appear with no IP address(default set to
+		// 0.0.0.0), ignore it
+		for (IPv4Address i : ips) {
+			if (i.getInt() != 0) {
 				ip = IPv4.fromIPv4Address(i.getInt());
 				break;
 			}
 		}
-		
-		logger.info("New AP added. [dpid:" + dpid + " ip:" + ip + "]");
+
+		logger.debug("AP(dpid:{},ip:{}) is added", dpid, ip);
 		AP ap = new AP(ip, dpid);
 		apManager.addAP(ap);
 		processAPAdded(ap);
@@ -419,7 +444,7 @@ public class ACL implements IACLService, IFloodlightModule, IDeviceListener {
 
 	@Override
 	public String getName() {
-		return null;
+		return "ACL manager";
 	}
 
 	@Override
diff --git a/src/main/java/net/floodlightcontroller/accesscontrollist/IACLService.java b/src/main/java/net/floodlightcontroller/accesscontrollist/IACLService.java
index 9ce23238e..50e0c0804 100644
--- a/src/main/java/net/floodlightcontroller/accesscontrollist/IACLService.java
+++ b/src/main/java/net/floodlightcontroller/accesscontrollist/IACLService.java
@@ -1,42 +1,56 @@
-/**
- *    Copyright 2015, Big Switch Networks, Inc.
- *    Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China 
- *    Advisers: Keqiu Li and Heng Qi 
- *    This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002) 
- *    and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
- *    
- *    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.accesscontrollist;
-
-import java.util.List;
-
-import net.floodlightcontroller.core.module.IFloodlightService;
-
-public interface IACLService extends IFloodlightService {
-	
-    public List<ACLRule> getRules();
-    
-    /**
-     * add a new ACL rule
-     * @param rule
-     * @return whether the rule is added successfully
-     */
-    public boolean addRule(ACLRule rule);
-
-    public void removeRule(int ruleid);
-    
-    public void removeAllRules();
-
-}
+/**
+ *    Copyright 2015, Big Switch Networks, Inc.
+ *    Originally created by Pengfei Lu, Network and Cloud Computing Laboratory, Dalian University of Technology, China 
+ *    Advisers: Keqiu Li and Heng Qi 
+ *    This work is supported by the State Key Program of National Natural Science of China(Grant No. 61432002) 
+ *    and Prospective Research Project on Future Networks in Jiangsu Future Networks Innovation Institute.
+ *    
+ *    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.accesscontrollist;
+
+import java.util.List;
+
+import net.floodlightcontroller.core.module.IFloodlightService;
+
+/**
+ * Service interface exported by ACL module
+ */
+public interface IACLService extends IFloodlightService {
+	
+    /**
+     * Gets a list containing all ACL rules.
+     * @return a list containing all ACL rules
+     */
+    public List<ACLRule> getRules();
+    
+    /**
+     * Add a new ACL rule.
+     * @param rule ACL rule
+     * @return true if successfully added, otherwise false
+     */
+    public boolean addRule(ACLRule rule);
+
+    /**
+     * Removes an existing ACL rule by rule id.
+     * @param ruleId ACL rule identifier
+     */
+    public void removeRule(int ruleid);
+    
+    /**
+     * Clears ACL and resets all.
+     */
+    public void removeAllRules();
+
+}
-- 
GitLab