Merge "ACL: Enabling ACL service in the pipeline"
[netvirt.git] / vpnservice / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / AbstractAclServiceImpl.java
index ad3fd2996f33f129e3fd0a4b4d6f1ab2782d6ab2..f4c6e72cd3be390172541d10a51fe01ccf6766ec 100644 (file)
@@ -10,6 +10,8 @@ package org.opendaylight.netvirt.aclservice;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.ActionType;
@@ -23,7 +25,9 @@ import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.netvirt.aclservice.api.AclServiceListener;
 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.Action;
 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
+import org.opendaylight.netvirt.aclservice.api.utils.AclInterfaceCacheUtil;
 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
+import org.opendaylight.netvirt.aclservice.utils.AclDataUtil;
 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
@@ -37,16 +41,19 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
 
     private static final Logger LOG = LoggerFactory.getLogger(AbstractAclServiceImpl.class);
 
-    private final IMdsalApiManager mdsalManager;
-    private final Class<? extends ServiceModeBase> serviceMode;
+    protected final IMdsalApiManager mdsalManager;
     protected final DataBroker dataBroker;
+    protected final Class<? extends ServiceModeBase> serviceMode;
 
     /**
      * Initialize the member variables.
      *
-     * @param serviceMode the service mode
-     * @param dataBroker the data broker instance.
-     * @param mdsalManager the mdsal manager instance.
+     * @param serviceMode
+     *            the service mode
+     * @param dataBroker
+     *            the data broker instance.
+     * @param mdsalManager
+     *            the mdsal manager instance.
      */
     public AbstractAclServiceImpl(Class<? extends ServiceModeBase> serviceMode, DataBroker dataBroker,
             IMdsalApiManager mdsalManager) {
@@ -57,18 +64,19 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
 
     @Override
     public boolean applyAcl(AclInterface port) {
+        if (port == null) {
+            LOG.error("port cannot be null");
+            return false;
+        }
         BigInteger dpId = port.getDpId();
-        if (dpId == null) {
+        if (dpId == null || port.getLPortTag() == null) {
             LOG.error("Unable to find DP Id from ACL interface with id {}", port.getInterfaceId());
             return false;
         }
-
         programAclWithAllowedAddress(dpId, port.getAllowedAddressPairs(), port.getLPortTag(), port.getSecurityGroups(),
-                Action.ADD, NwConstants.ADD_FLOW);
+                Action.ADD, NwConstants.ADD_FLOW, port.getInterfaceId());
 
-        // TODO: uncomment bindservice() when the acl flow programming is
-        // implemented
-        // bindService(port.getName());
+        bindService(port.getInterfaceId());
         return true;
     }
 
@@ -102,11 +110,11 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
                         portAfter.getAllowedAddressPairs());
         if (addedAllowedAddressPairs != null && !addedAllowedAddressPairs.isEmpty()) {
             programAclWithAllowedAddress(dpId, addedAllowedAddressPairs, portAfter.getLPortTag(),
-                    portAfter.getSecurityGroups(), Action.UPDATE, NwConstants.ADD_FLOW);
+                    portAfter.getSecurityGroups(), Action.UPDATE, NwConstants.ADD_FLOW, portAfter.getInterfaceId());
         }
         if (deletedAllowedAddressPairs != null && !deletedAllowedAddressPairs.isEmpty()) {
             programAclWithAllowedAddress(dpId, deletedAllowedAddressPairs, portAfter.getLPortTag(),
-                    portAfter.getSecurityGroups(), Action.UPDATE, NwConstants.DEL_FLOW);
+                    portAfter.getSecurityGroups(), Action.UPDATE, NwConstants.DEL_FLOW, portAfter.getInterfaceId());
         }
 
         List<Uuid> addedAcls = AclServiceUtils.getUpdatedAclList(portAfter.getSecurityGroups(),
@@ -114,25 +122,53 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         List<Uuid> deletedAcls = AclServiceUtils.getUpdatedAclList(portBefore.getSecurityGroups(),
                 portAfter.getSecurityGroups());
         if (addedAcls != null && !addedAcls.isEmpty()) {
-            updateCustomRules(dpId, portAfter.getLPortTag(), addedAcls, NwConstants.ADD_FLOW);
+            updateCustomRules(dpId, portAfter.getLPortTag(), addedAcls, NwConstants.ADD_FLOW,
+                    portAfter.getInterfaceId(), portAfter.getAllowedAddressPairs());
         }
         if (deletedAcls != null && !deletedAcls.isEmpty()) {
-            updateCustomRules(dpId, portAfter.getLPortTag(), deletedAcls, NwConstants.DEL_FLOW);
+            updateCustomRules(dpId, portAfter.getLPortTag(), deletedAcls, NwConstants.DEL_FLOW,
+                    portAfter.getInterfaceId(), portAfter.getAllowedAddressPairs());
         }
     }
 
-    private void updateCustomRules(BigInteger dpId, int lportTag, List<Uuid> aclUuidList, int action) {
-        programAclRules(aclUuidList, dpId, lportTag, action);
+    private void updateCustomRules(BigInteger dpId, int lportTag, List<Uuid> aclUuidList, int action,
+                                   String portId, List<AllowedAddressPairs> syncAllowedAddresses) {
+        programAclRules(aclUuidList, dpId, lportTag, action, portId);
+        syncRemoteAclRules(aclUuidList, action, portId, syncAllowedAddresses);
+    }
+
+    private void syncRemoteAclRules(List<Uuid> aclUuidList, int action, String currentPortId,
+                                    List<AllowedAddressPairs> syncAllowedAddresses) {
+        for (Uuid remoteAclId : aclUuidList) {
+            Set<String> portSet = AclDataUtil.getRemoteAclInterfaces(remoteAclId);
+            if (portSet == null) {
+                continue;
+            }
+            for (String remotePortId : portSet) {
+                AclInterface port = AclInterfaceCacheUtil.getAclInterfaceFromCache(remotePortId);
+                if (currentPortId.equals(port.getInterfaceId())) {
+                    continue;
+                }
+                List<Ace> remoteAceList = AclServiceUtils.getAceWithRemoteAclId(dataBroker, port, remoteAclId);
+                for (Ace ace : remoteAceList) {
+                    programAceRule(port.getDpId(), port.getLPortTag(), action, ace, port.getInterfaceId(),
+                            syncAllowedAddresses);
+                }
+            }
+        }
     }
 
     private void programAclWithAllowedAddress(BigInteger dpId, List<AllowedAddressPairs> allowedAddresses,
-            int lportTag, List<Uuid> aclUuidList, Action action, int addOrRemove) {
+                                              int lportTag, List<Uuid> aclUuidList, Action action, int addOrRemove,
+                                              String portId) {
         programFixedRules(dpId, "", allowedAddresses, lportTag, action, addOrRemove);
         if (action == Action.ADD || action == Action.REMOVE) {
-            programAclRules(aclUuidList, dpId, lportTag, addOrRemove);
+            programAclRules(aclUuidList, dpId, lportTag, addOrRemove, portId);
         }
+        syncRemoteAclRules(aclUuidList, addOrRemove, portId, allowedAddresses);
     }
 
+
     @Override
     public boolean removeAcl(AclInterface port) {
         BigInteger dpId = port.getDpId();
@@ -140,12 +176,10 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
             LOG.error("Unable to find DP Id from ACL interface with id {}", port.getInterfaceId());
             return false;
         }
-
         programAclWithAllowedAddress(dpId, port.getAllowedAddressPairs(), port.getLPortTag(), port.getSecurityGroups(),
-                Action.REMOVE, NwConstants.DEL_FLOW);
-        // TODO: uncomment unbindService() when the acl flow programming is
-        // implemented
-        // unbindService(port.getName());
+                Action.REMOVE, NwConstants.DEL_FLOW, port.getInterfaceId());
+
+        unbindService(port.getInterfaceId());
         return true;
     }
 
@@ -154,7 +188,8 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         if (!port.isPortSecurityEnabled()) {
             return false;
         }
-        programAceRule(port.getDpId(), port.getLPortTag(), NwConstants.ADD_FLOW, ace);
+        programAceRule(port.getDpId(), port.getLPortTag(), NwConstants.ADD_FLOW, ace,
+                port.getInterfaceId(), null);
         return true;
     }
 
@@ -163,22 +198,24 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         if (!port.isPortSecurityEnabled()) {
             return false;
         }
-        programAceRule(port.getDpId(), port.getLPortTag(), NwConstants.DEL_FLOW, ace);
+        programAceRule(port.getDpId(), port.getLPortTag(), NwConstants.DEL_FLOW, ace,
+                port.getInterfaceId(), null);
         return true;
     }
 
-
     /**
      * Bind service.
      *
-     * @param interfaceName the interface name
+     * @param interfaceName
+     *            the interface name
      */
     protected abstract void bindService(String interfaceName);
 
     /**
      * Unbind service.
      *
-     * @param interfaceName the interface name
+     * @param interfaceName
+     *            the interface name
      */
     protected abstract void unbindService(String interfaceName);
 
@@ -203,7 +240,8 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
      * @param lportTag the lport tag
      * @param addOrRemove whether to delete or add flow
      */
-    protected abstract void programAclRules(List<Uuid> aclUuidList, BigInteger dpId, int lportTag, int addOrRemove);
+    protected abstract boolean programAclRules(List<Uuid> aclUuidList, BigInteger dpId, int lportTag, int addOrRemove,
+                                            String portId);
 
     /**
      * Programs the ace custom rule.
@@ -213,33 +251,46 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
      * @param addOrRemove whether to delete or add flow
      * @param ace rule to be program
      */
-    protected abstract void programAceRule(BigInteger dpId, int lportTag, int addOrRemove, Ace ace);
+    protected abstract void programAceRule(BigInteger dpId, int lportTag, int addOrRemove, Ace ace, String portId,
+                                           List<AllowedAddressPairs> syncAllowedAddresses);
 
     /**
      * Writes/remove the flow to/from the datastore.
-     * @param dpId the dpId
-     * @param tableId the tableId
-     * @param flowId the flowId
-     * @param priority the priority
-     * @param flowName the flow name
-     * @param idleTimeOut the idle timeout
-     * @param hardTimeOut the hard timeout
-     * @param cookie the cookie
-     * @param matches the list of matches to be writted
-     * @param instructions the list of instruction to be written.
-     * @param addOrRemove add or remove the entries.
+     *
+     * @param dpId
+     *            the dpId
+     * @param tableId
+     *            the tableId
+     * @param flowId
+     *            the flowId
+     * @param priority
+     *            the priority
+     * @param flowName
+     *            the flow name
+     * @param idleTimeOut
+     *            the idle timeout
+     * @param hardTimeOut
+     *            the hard timeout
+     * @param cookie
+     *            the cookie
+     * @param matches
+     *            the list of matches to be writted
+     * @param instructions
+     *            the list of instruction to be written.
+     * @param addOrRemove
+     *            add or remove the entries.
      */
     protected void syncFlow(BigInteger dpId, short tableId, String flowId, int priority, String flowName,
-                          int idleTimeOut, int hardTimeOut, BigInteger cookie, List<? extends MatchInfoBase>  matches,
-                          List<InstructionInfo> instructions, int addOrRemove) {
+            int idleTimeOut, int hardTimeOut, BigInteger cookie, List<? extends MatchInfoBase> matches,
+            List<InstructionInfo> instructions, int addOrRemove) {
         if (addOrRemove == NwConstants.DEL_FLOW) {
-            FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,flowId,
-                priority, flowName , idleTimeOut, hardTimeOut, cookie, matches, null);
+            FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority, flowName, idleTimeOut,
+                    hardTimeOut, cookie, matches, null);
             LOG.trace("Removing Acl Flow DpnId {}, flowId {}", dpId, flowId);
             mdsalManager.removeFlow(flowEntity);
         } else {
-            FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId,
-                priority, flowName, idleTimeOut, hardTimeOut, cookie, matches, instructions);
+            FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority, flowName, idleTimeOut,
+                    hardTimeOut, cookie, matches, instructions);
             LOG.trace("Installing DpnId {}, flowId {}", dpId, flowId);
             mdsalManager.installFlow(flowEntity);
         }
@@ -263,4 +314,22 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
         return instructions;
     }
+
+    protected String getOperAsString(int flowOper) {
+        String oper;
+        switch (flowOper) {
+            case NwConstants.ADD_FLOW:
+                oper = "Add";
+                break;
+            case NwConstants.DEL_FLOW:
+                oper = "Del";
+                break;
+            case NwConstants.MOD_FLOW:
+                oper = "Mod";
+                break;
+            default:
+                oper = "UNKNOWN";
+        }
+        return oper;
+    }
 }