MRI version bumpup for Aluminium
[netvirt.git] / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / listeners / AclInterfaceListener.java
index c32514988ee29f294ef8071a45926b98b06ba865..dec684b56eba8929a10369c5346ac4456bc7aabb 100644 (file)
@@ -7,20 +7,16 @@
  */
 package org.opendaylight.netvirt.aclservice.listeners;
 
-import com.google.common.util.concurrent.Futures;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
-import java.util.concurrent.ExecutionException;
-import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
-import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
-import org.opendaylight.genius.srm.RecoverableListener;
-import org.opendaylight.genius.srm.ServiceRecoveryRegistry;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.infrautils.utils.concurrent.Executors;
+import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.netvirt.aclservice.api.AclInterfaceCache;
 import org.opendaylight.netvirt.aclservice.api.AclServiceManager;
 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.Action;
@@ -28,6 +24,9 @@ import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
 import org.opendaylight.netvirt.aclservice.utils.AclClusterUtil;
 import org.opendaylight.netvirt.aclservice.utils.AclDataUtil;
 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
+import org.opendaylight.serviceutils.srm.RecoverableListener;
+import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
+import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
@@ -35,12 +34,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionIngress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.SubnetInfo;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Singleton
-public class AclInterfaceListener extends AsyncDataTreeChangeListenerBase<Interface, AclInterfaceListener>
+public class AclInterfaceListener extends AbstractAsyncDataTreeChangeListener<Interface>
         implements ClusteredDataTreeChangeListener<Interface>, RecoverableListener {
     private static final Logger LOG = LoggerFactory.getLogger(AclInterfaceListener.class);
 
@@ -55,7 +56,9 @@ public class AclInterfaceListener extends AsyncDataTreeChangeListenerBase<Interf
     public AclInterfaceListener(AclServiceManager aclServiceManager, AclClusterUtil aclClusterUtil,
             DataBroker dataBroker, AclDataUtil aclDataUtil, AclInterfaceCache aclInterfaceCache,
             AclServiceUtils aclServicUtils, ServiceRecoveryRegistry serviceRecoveryRegistry) {
-        super(Interface.class, AclInterfaceListener.class);
+        super(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                InstanceIdentifier.create(Interfaces.class).child(Interface.class),
+                Executors.newListeningSingleThreadExecutor("AclEventListener", LOG));
         this.aclServiceManager = aclServiceManager;
         this.aclClusterUtil = aclClusterUtil;
         this.dataBroker = dataBroker;
@@ -65,21 +68,18 @@ public class AclInterfaceListener extends AsyncDataTreeChangeListenerBase<Interf
         serviceRecoveryRegistry.addRecoverableListener(AclServiceUtils.getRecoverServiceRegistryKey(), this);
     }
 
-    @Override
-    @PostConstruct
     public void init() {
         LOG.info("{} start", getClass().getSimpleName());
-        registerListener();
     }
 
     @Override
     public void registerListener() {
-        registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+        super.register();
     }
 
     @Override
-    protected InstanceIdentifier<Interface> getWildCardPath() {
-        return InstanceIdentifier.create(Interfaces.class).child(Interface.class);
+    public void deregisterListener() {
+        super.close();
     }
 
     @Override
@@ -94,21 +94,20 @@ public class AclInterfaceListener extends AsyncDataTreeChangeListenerBase<Interf
                 if (aclInterface.getDpId() != null) {
                     aclServiceManager.notify(aclInterface, null, Action.REMOVE);
                 }
-                AclServiceUtils.deleteSubnetIpPrefixes(dataBroker, interfaceId);
             }
         }
     }
 
     @Override
-    public void update(InstanceIdentifier<Interface> key, Interface portBefore, Interface portAfter) {
-        if (portBefore.getAugmentation(ParentRefs.class) == null
-                && portAfter.getAugmentation(ParentRefs.class) != null) {
+    public void update(@Nullable InstanceIdentifier<Interface> key, Interface portBefore, Interface portAfter) {
+        if (portBefore.augmentation(ParentRefs.class) == null
+                && portAfter.augmentation(ParentRefs.class) != null) {
             LOG.trace("Ignoring event for update in ParentRefs for {} ", portAfter.getName());
             return;
         }
         LOG.trace("Received AclInterface update event, portBefore={}, portAfter={}", portBefore, portAfter);
-        InterfaceAcl aclInPortAfter = portAfter.getAugmentation(InterfaceAcl.class);
-        InterfaceAcl aclInPortBefore = portBefore.getAugmentation(InterfaceAcl.class);
+        InterfaceAcl aclInPortAfter = portAfter.augmentation(InterfaceAcl.class);
+        InterfaceAcl aclInPortBefore = portBefore.augmentation(InterfaceAcl.class);
 
         String interfaceId = portAfter.getName();
         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
@@ -120,12 +119,15 @@ public class AclInterfaceListener extends AsyncDataTreeChangeListenerBase<Interf
             // port-security-enable=false
             aclInterfaceBefore = addOrUpdateAclInterfaceCache(interfaceId, aclInPortBefore, true, interfaceState);
         }
-        if (aclInPortAfter != null && aclInPortAfter.isPortSecurityEnabled()
-                || aclInPortBefore != null && aclInPortBefore.isPortSecurityEnabled()) {
-            boolean isSgChanged =
-                    isSecurityGroupsChanged(aclInPortBefore.getSecurityGroups(), aclInPortAfter.getSecurityGroups());
+        if (AclServiceUtils.isOfInterest(aclInPortAfter) || AclServiceUtils.isOfInterest(aclInPortBefore)) {
+            List<Uuid> sgsBefore = null;
+            if (aclInPortBefore != null) {
+                sgsBefore = aclInPortBefore.getSecurityGroups();
+            }
+            boolean isSgChanged = isSecurityGroupsChanged(sgsBefore, aclInPortAfter.getSecurityGroups());
             AclInterface aclInterfaceAfter =
                     addOrUpdateAclInterfaceCache(interfaceId, aclInPortAfter, isSgChanged, interfaceState);
+            updateCacheWithAddedAcls(aclInterfaceBefore, aclInterfaceAfter);
 
             if (aclClusterUtil.isEntityOwner()) {
                 // Handle bind/unbind service irrespective of interface state (up/down)
@@ -137,9 +139,8 @@ public class AclInterfaceListener extends AsyncDataTreeChangeListenerBase<Interf
                             isPortSecurityEnable);
                     aclServiceManager.notify(aclInterfaceAfter, null, Action.UNBIND);
                 }
-                if (interfaceState != null && interfaceState.getOperStatus().equals(
-                        org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
-                            .state.Interface.OperStatus.Up)) {
+                if (interfaceState != null && org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces
+                        .rev140508.interfaces.state.Interface.OperStatus.Up.equals(interfaceState.getOperStatus())) {
                     // if port security enable is changed and is enabled, bind ACL service
                     if (isPortSecurityEnableBefore != isPortSecurityEnable && isPortSecurityEnable) {
                         LOG.debug("Notify bind ACL service for interface={}, isPortSecurityEnable={}", interfaceId,
@@ -149,21 +150,11 @@ public class AclInterfaceListener extends AsyncDataTreeChangeListenerBase<Interf
                     LOG.debug("On update event, notify ACL service manager to update ACL for interface: {}",
                             interfaceId);
                     // handle add for AclPortsLookup before processing update
-                    try {
-                        Futures.allAsList(aclServiceUtils.addAclPortsLookupForInterfaceUpdate(aclInterfaceBefore,
-                                aclInterfaceAfter)).get();
-                    } catch (InterruptedException | ExecutionException e) {
-                        LOG.error("Error adding ACL ports for interface update", e);
-                    }
+                    aclServiceUtils.addAclPortsLookupForInterfaceUpdate(aclInterfaceBefore, aclInterfaceAfter);
 
                     aclServiceManager.notify(aclInterfaceAfter, aclInterfaceBefore, AclServiceManager.Action.UPDATE);
                     // handle delete for AclPortsLookup after processing update
-                    try {
-                        Futures.allAsList(aclServiceUtils.deleteAclPortsLookupForInterfaceUpdate(aclInterfaceBefore,
-                                aclInterfaceAfter)).get();
-                    } catch (InterruptedException | ExecutionException e) {
-                        LOG.error("Error deleting ACL ports for interface update", e);
-                    }
+                    aclServiceUtils.deleteAclPortsLookupForInterfaceUpdate(aclInterfaceBefore, aclInterfaceAfter);
                 }
             }
             updateCacheWithAclChange(aclInterfaceBefore, aclInterfaceAfter);
@@ -171,14 +162,26 @@ public class AclInterfaceListener extends AsyncDataTreeChangeListenerBase<Interf
     }
 
     private void updateCacheWithAclChange(AclInterface aclInterfaceBefore, AclInterface aclInterfaceAfter) {
-        List<Uuid> addedAcls = AclServiceUtils.getUpdatedAclList(aclInterfaceAfter.getSecurityGroups(),
-                aclInterfaceBefore.getSecurityGroups());
         List<Uuid> deletedAcls = AclServiceUtils.getUpdatedAclList(aclInterfaceBefore.getSecurityGroups(),
                 aclInterfaceAfter.getSecurityGroups());
-        if (deletedAcls != null && !deletedAcls.isEmpty()) {
+        if (!deletedAcls.isEmpty()) {
             aclDataUtil.removeAclInterfaceMap(deletedAcls, aclInterfaceAfter);
         }
+        List<AllowedAddressPairs> addedAap = AclServiceUtils.getUpdatedAllowedAddressPairs(aclInterfaceAfter
+                .getAllowedAddressPairs(), aclInterfaceBefore.getAllowedAddressPairs());
+        List<AllowedAddressPairs> deletedAap = AclServiceUtils.getUpdatedAllowedAddressPairs(aclInterfaceBefore
+                .getAllowedAddressPairs(), aclInterfaceAfter.getAllowedAddressPairs());
+        if (!deletedAap.isEmpty() || !addedAap.isEmpty()) {
+            LOG.debug("Update cache with new AAP = {}", aclInterfaceAfter.getInterfaceId());
+            aclDataUtil.addOrUpdateAclInterfaceMap(aclInterfaceAfter.getSecurityGroups(), aclInterfaceAfter);
+        }
+    }
+
+    private void updateCacheWithAddedAcls(AclInterface aclInterfaceBefore, AclInterface aclInterfaceAfter) {
+        List<Uuid> addedAcls = AclServiceUtils.getUpdatedAclList(aclInterfaceAfter.getSecurityGroups(),
+                aclInterfaceBefore.getSecurityGroups());
         if (addedAcls != null && !addedAcls.isEmpty()) {
+            LOG.debug("Update cache by adding interface={}", aclInterfaceAfter.getInterfaceId());
             aclDataUtil.addOrUpdateAclInterfaceMap(addedAcls, aclInterfaceAfter);
         }
     }
@@ -188,17 +191,14 @@ public class AclInterfaceListener extends AsyncDataTreeChangeListenerBase<Interf
                 && aclInPortAfter.isPortSecurityEnabled();
     }
 
-    private boolean isSecurityGroupsChanged(List<Uuid> sgsBefore, List<Uuid> sgsAfter) {
+    private boolean isSecurityGroupsChanged(@Nullable List<Uuid> sgsBefore, @Nullable List<Uuid> sgsAfter) {
         if (sgsBefore == null && sgsAfter == null) {
             return false;
         }
-        if ((sgsBefore == null && sgsAfter != null) || (sgsBefore != null && sgsAfter == null)) {
+        if (sgsBefore == null || sgsAfter == null) {
             return true;
         }
-        if (sgsBefore != null && sgsAfter != null) {
-            return !(new HashSet<>(sgsBefore)).equals(new HashSet<>(sgsAfter));
-        }
-        return true;
+        return !(sgsBefore.containsAll(sgsAfter) && sgsAfter.containsAll(sgsBefore));
     }
 
     private AclInterface addOrUpdateAclInterfaceCache(String interfaceId, InterfaceAcl aclInPort) {
@@ -207,13 +207,16 @@ public class AclInterfaceListener extends AsyncDataTreeChangeListenerBase<Interf
 
     private AclInterface addOrUpdateAclInterfaceCache(String interfaceId, InterfaceAcl aclInPort, boolean isSgChanged,
             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
-                    .Interface interfaceState) {
+                .@Nullable Interface interfaceState) {
         AclInterface aclInterface = aclInterfaceCache.addOrUpdate(interfaceId, (prevAclInterface, builder) -> {
             List<Uuid> sgs = new ArrayList<>();
             if (aclInPort != null) {
                 sgs = aclInPort.getSecurityGroups();
-                builder.portSecurityEnabled(aclInPort.isPortSecurityEnabled()).securityGroups(sgs)
-                        .allowedAddressPairs(aclInPort.getAllowedAddressPairs());
+                builder.portSecurityEnabled(aclInPort.isPortSecurityEnabled())
+                        .interfaceType(aclInPort.getInterfaceType()).securityGroups(sgs)
+                        .allowedAddressPairs(new ArrayList<AllowedAddressPairs>(aclInPort
+                                .getAllowedAddressPairs().values())).subnetInfo(new ArrayList<SubnetInfo>(aclInPort
+                        .getSubnetInfo().values()));
             }
 
             if ((prevAclInterface == null || prevAclInterface.getLPortTag() == null) && interfaceState != null) {
@@ -221,9 +224,6 @@ public class AclInterfaceListener extends AsyncDataTreeChangeListenerBase<Interf
                         .lPortTag(interfaceState.getIfIndex()).isMarkedForDelete(false);
             }
 
-            if (prevAclInterface == null) {
-                builder.subnetIpPrefixes(AclServiceUtils.getSubnetIpPrefixes(dataBroker, interfaceId));
-            }
             if (prevAclInterface == null || prevAclInterface.getElanId() == null) {
                 builder.elanId(AclServiceUtils.getElanIdFromInterface(interfaceId, dataBroker));
             }
@@ -239,8 +239,8 @@ public class AclInterfaceListener extends AsyncDataTreeChangeListenerBase<Interf
     @Override
     public void add(InstanceIdentifier<Interface> key, Interface port) {
         LOG.trace("Received AclInterface add event, port={}", port);
-        InterfaceAcl aclInPort = port.getAugmentation(InterfaceAcl.class);
-        if (aclInPort != null && aclInPort.isPortSecurityEnabled()) {
+        InterfaceAcl aclInPort = port.augmentation(InterfaceAcl.class);
+        if (AclServiceUtils.isOfInterest(aclInPort)) {
             String interfaceId = port.getName();
             AclInterface aclInterface = addOrUpdateAclInterfaceCache(interfaceId, aclInPort);
 
@@ -254,7 +254,9 @@ public class AclInterfaceListener extends AsyncDataTreeChangeListenerBase<Interf
     }
 
     @Override
-    protected AclInterfaceListener getDataTreeChangeListener() {
-        return this;
+    @PreDestroy
+    public void close() {
+        super.close();
+        Executors.shutdownAndAwaitTermination(getExecutorService());
     }
 }