ACL: Handle AAP update 98/68498/2
authorSomashekar Byrappa <somashekar.b@altencalsoftlabs.com>
Thu, 22 Feb 2018 15:07:28 +0000 (20:37 +0530)
committerSam Hague <shague@redhat.com>
Sat, 24 Feb 2018 02:29:53 +0000 (02:29 +0000)
During port-update with add of allowed-address-pair (IP/MAC),
corresponding flows were not added in table=210 for egressAclDhcpAllowClientTraffic()
and egressAclDhcpv6AllowClientTraffic(). This issue is addressed with the
patch.

Also, avoided configuring flows related AAPs with multicast addresses in
VM egress anti-spoofing table (table=210) as the source address will never be
multicast address.

Change-Id: Ibe66cc65a484864c53a085b70d2aa37486e662d4
Signed-off-by: Somashekar Byrappa <somashekar.b@altencalsoftlabs.com>
aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/AbstractAclServiceImpl.java
aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/EgressAclServiceImpl.java
aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/IngressAclServiceImpl.java
aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/utils/AclServiceUtils.java
aclservice/impl/src/test/java/org/opendaylight/netvirt/aclservice/utils/AclServiceUtilsTest.java [new file with mode: 0644]

index f4c4d49e2f11e86cb83672b947f0ce54ab9d6f60..3b220a8d02dc2e3c4dcd0926a9531ecc97d858e0 100644 (file)
@@ -185,7 +185,6 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
     }
 
     private void processInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
-        BigInteger dpId = portAfter.getDpId();
         List<AllowedAddressPairs> addedAaps = AclServiceUtils
                 .getUpdatedAllowedAddressPairs(portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs());
         List<AllowedAddressPairs> deletedAaps = AclServiceUtils
@@ -198,7 +197,6 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
             programAclWithAllowedAddress(portAfter, addedAaps, Action.UPDATE, NwConstants.ADD_FLOW);
             updateRemoteAclFilterTable(portAfter, portAfter.getSecurityGroups(), addedAaps, NwConstants.ADD_FLOW);
         }
-        updateArpForAllowedAddressPairs(dpId, portAfter.getLPortTag(), deletedAaps, portAfter.getAllowedAddressPairs());
         if (portAfter.getSubnetIpPrefixes() != null && portBefore.getSubnetIpPrefixes() == null) {
             programBroadcastRules(portAfter, NwConstants.ADD_FLOW);
         }
@@ -299,7 +297,7 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
         int lportTag = port.getLPortTag();
         LOG.debug("Applying ACL Allowed Address on DpId {}, lportTag {}, Action {}", dpId, lportTag, action);
         String portId = port.getInterfaceId();
-        programAntiSpoofingRules(port, "", allowedAddresses, action, addOrRemove);
+        programAntiSpoofingRules(port, allowedAddresses, action, addOrRemove);
         programAclPortSpecificFixedRules(dpId, allowedAddresses, lportTag, portId, action, addOrRemove);
         if (action == Action.ADD || action == Action.REMOVE) {
             programAclRules(port, port.getSecurityGroups(), addOrRemove);
@@ -504,24 +502,12 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener {
      * Programs the anti-spoofing rules.
      *
      * @param port the acl interface
-     * @param dhcpMacAddress the dhcp mac address.
      * @param allowedAddresses the allowed addresses
      * @param action add/modify/remove action
      * @param addOrRemove addorRemove
      */
-    protected abstract void programAntiSpoofingRules(AclInterface port, String dhcpMacAddress,
-            List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove);
-
-    /**
-     * Update arp for allowed address pairs.
-     *
-     * @param dpId the dp id
-     * @param lportTag the lport tag
-     * @param deletedAAP the deleted allowed address pairs
-     * @param addedAAP the added allowed address pairs
-     */
-    protected abstract void updateArpForAllowedAddressPairs(BigInteger dpId, int lportTag,
-            List<AllowedAddressPairs> deletedAAP, List<AllowedAddressPairs> addedAAP);
+    protected abstract void programAntiSpoofingRules(AclInterface port, List<AllowedAddressPairs> allowedAddresses,
+            Action action, int addOrRemove);
 
     /**
      * Programs broadcast rules.
index d17e7415c90c55a532eeb7b6ab15e02bbd3723e3..4aa4881d2f1a34edf86a13e678bba93ada8b1acd 100644 (file)
@@ -112,35 +112,25 @@ public class EgressAclServiceImpl extends AbstractAclServiceImpl {
     }
 
     @Override
-    protected void programAntiSpoofingRules(AclInterface port, String dhcpMacAddress,
-            List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove) {
+    protected void programAntiSpoofingRules(AclInterface port, List<AllowedAddressPairs> allowedAddresses,
+            Action action, int addOrRemove) {
         LOG.info("{} programAntiSpoofingRules for port {}, AAPs={}, action={}, addOrRemove={}", this.directionString,
                 port.getInterfaceId(), allowedAddresses, action, addOrRemove);
 
         BigInteger dpid = port.getDpId();
         int lportTag = port.getLPortTag();
-        if (action == Action.ADD || action == Action.REMOVE) {
-            Set<MacAddress> aapMacs =
-                allowedAddresses.stream().map(aap -> aap.getMacAddress()).collect(Collectors.toSet());
-            egressAclDhcpAllowClientTraffic(dpid, aapMacs, lportTag, addOrRemove);
-            egressAclDhcpv6AllowClientTraffic(dpid, aapMacs, lportTag, addOrRemove);
-            egressAclDhcpDropServerTraffic(dpid, dhcpMacAddress, lportTag, addOrRemove);
-            egressAclDhcpv6DropServerTraffic(dpid, dhcpMacAddress, lportTag, addOrRemove);
+        if (action != Action.UPDATE) {
+            egressAclDhcpDropServerTraffic(dpid, lportTag, addOrRemove);
+            egressAclDhcpv6DropServerTraffic(dpid, lportTag, addOrRemove);
             egressAclIcmpv6DropRouterAdvts(dpid, lportTag, addOrRemove);
             egressAclIcmpv6AllowedList(dpid, lportTag, addOrRemove);
-
-            programArpRule(dpid, allowedAddresses, lportTag, addOrRemove);
             programL2BroadcastAllowRule(port, addOrRemove);
         }
-    }
+        List<AllowedAddressPairs> filteredAAPs = AclServiceUtils.excludeMulticastAAPs(allowedAddresses);
 
-    @Override
-    protected void updateArpForAllowedAddressPairs(BigInteger dpId, int lportTag, List<AllowedAddressPairs> deletedAAP,
-            List<AllowedAddressPairs> addedAAP) {
-        // Remove common allowedAddrPairIPs to avoid delete and add of ARP flows having same MAC and IP
-        deletedAAP.removeAll(addedAAP);
-        programArpRule(dpId, deletedAAP, lportTag, NwConstants.DEL_FLOW);
-        programArpRule(dpId, addedAAP, lportTag, NwConstants.ADD_FLOW);
+        egressAclDhcpAllowClientTraffic(dpid, filteredAAPs, lportTag, addOrRemove);
+        egressAclDhcpv6AllowClientTraffic(dpid, filteredAAPs, lportTag, addOrRemove);
+        programArpRule(dpid, filteredAAPs, lportTag, addOrRemove);
     }
 
     @Override
@@ -159,7 +149,8 @@ public class EgressAclServiceImpl extends AbstractAclServiceImpl {
     @Override
     protected void programGotoClassifierTableRules(BigInteger dpId, List<AllowedAddressPairs> aaps, int lportTag,
             int addOrRemove) {
-        for (AllowedAddressPairs aap : aaps) {
+        List<AllowedAddressPairs> filteredAAPs = AclServiceUtils.excludeMulticastAAPs(aaps);
+        for (AllowedAddressPairs aap : filteredAAPs) {
             IpPrefixOrAddress attachIp = aap.getIpAddress();
             MacAddress mac = aap.getMacAddress();
 
@@ -182,16 +173,14 @@ public class EgressAclServiceImpl extends AbstractAclServiceImpl {
      * Anti-spoofing rule to block the Ipv4 DHCP server traffic from the port.
      *
      * @param dpId the dpId
-     * @param dhcpMacAddress the Dhcp mac address
      * @param lportTag the lport tag
      * @param addOrRemove add/remove the flow.
      */
-    protected void egressAclDhcpDropServerTraffic(BigInteger dpId, String dhcpMacAddress, int lportTag,
-            int addOrRemove) {
+    protected void egressAclDhcpDropServerTraffic(BigInteger dpId, int lportTag, int addOrRemove) {
         List<MatchInfoBase> matches = AclServiceUtils.buildDhcpMatches(AclConstants.DHCP_SERVER_PORT_IPV4,
                 AclConstants.DHCP_CLIENT_PORT_IPV4, lportTag, serviceMode);
 
-        String flowName = "Egress_DHCP_Server_v4" + dpId + "_" + lportTag + "_" + dhcpMacAddress + "_Drop_";
+        String flowName = "Egress_DHCP_Server_v4" + dpId + "_" + lportTag + "_Drop_";
         syncFlow(dpId, getAclAntiSpoofingTable(), flowName, AclConstants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY,
                 "ACL", 0, 0, AclConstants.COOKIE_ACL_BASE, matches, Collections.emptyList(), addOrRemove);
     }
@@ -200,16 +189,14 @@ public class EgressAclServiceImpl extends AbstractAclServiceImpl {
      * Anti-spoofing rule to block the Ipv6 DHCP server traffic from the port.
      *
      * @param dpId the dpId
-     * @param dhcpMacAddress the Dhcp mac address
      * @param lportTag the lport tag
      * @param addOrRemove add/remove the flow.
      */
-    protected void egressAclDhcpv6DropServerTraffic(BigInteger dpId, String dhcpMacAddress, int lportTag,
-            int addOrRemove) {
+    protected void egressAclDhcpv6DropServerTraffic(BigInteger dpId, int lportTag, int addOrRemove) {
         List<MatchInfoBase> matches = AclServiceUtils.buildDhcpV6Matches(AclConstants.DHCP_SERVER_PORT_IPV6,
                 AclConstants.DHCP_CLIENT_PORT_IPV6, lportTag, serviceMode);
 
-        String flowName = "Egress_DHCP_Server_v6" + "_" + dpId + "_" + lportTag + "_" + dhcpMacAddress + "_Drop_";
+        String flowName = "Egress_DHCP_Server_v6" + "_" + dpId + "_" + lportTag + "_Drop_";
         syncFlow(dpId, getAclAntiSpoofingTable(), flowName, AclConstants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY,
                 "ACL", 0, 0, AclConstants.COOKIE_ACL_BASE, matches, Collections.emptyList(), addOrRemove);
     }
@@ -249,24 +236,27 @@ public class EgressAclServiceImpl extends AbstractAclServiceImpl {
     }
 
     /**
-     * Add rule to ensure only DHCP server traffic from the specified mac is
-     * allowed.
+     * Add rule to ensure only DHCP server traffic from the specified mac is allowed.
      *
      * @param dpId the dpid
-     * @param aapMacs the AAP mac addresses
+     * @param allowedAddresses the allowed addresses
      * @param lportTag the lport tag
      * @param addOrRemove whether to add or remove the flow
      */
-    private void egressAclDhcpAllowClientTraffic(BigInteger dpId, Set<MacAddress> aapMacs, int lportTag,
-            int addOrRemove) {
+    private void egressAclDhcpAllowClientTraffic(BigInteger dpId, List<AllowedAddressPairs> allowedAddresses,
+            int lportTag, int addOrRemove) {
         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
-        for (MacAddress aapMac : aapMacs) {
+        for (AllowedAddressPairs aap : allowedAddresses) {
+            if (!AclServiceUtils.isIPv4Address(aap)) {
+                continue;
+            }
             List<MatchInfoBase> matches = new ArrayList<>();
             matches.addAll(AclServiceUtils.buildDhcpMatches(AclConstants.DHCP_CLIENT_PORT_IPV4,
                 AclConstants.DHCP_SERVER_PORT_IPV4, lportTag, serviceMode));
-            matches.add(new MatchEthernetSource(aapMac));
+            matches.add(new MatchEthernetSource(aap.getMacAddress()));
 
-            String flowName = "Egress_DHCP_Client_v4" + dpId + "_" + lportTag + "_" + aapMac.getValue() + "_Permit_";
+            String flowName =
+                    "Egress_DHCP_Client_v4" + dpId + "_" + lportTag + "_" + aap.getMacAddress().getValue() + "_Permit_";
             syncFlow(dpId, getAclAntiSpoofingTable(), flowName, AclConstants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY,
                     "ACL", 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
         }
@@ -277,21 +267,24 @@ public class EgressAclServiceImpl extends AbstractAclServiceImpl {
      * allowed.
      *
      * @param dpId the dpid
-     * @param aapMacs the AAP mac addresses
+     * @param allowedAddresses the allowed addresses
      * @param lportTag the lport tag
      * @param addOrRemove whether to add or remove the flow
      */
-    private void egressAclDhcpv6AllowClientTraffic(BigInteger dpId, Set<MacAddress> aapMacs, int lportTag,
-            int addOrRemove) {
+    private void egressAclDhcpv6AllowClientTraffic(BigInteger dpId, List<AllowedAddressPairs> allowedAddresses,
+            int lportTag, int addOrRemove) {
         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
-        for (MacAddress aapMac : aapMacs) {
+        for (AllowedAddressPairs aap : allowedAddresses) {
+            if (AclServiceUtils.isIPv4Address(aap)) {
+                continue;
+            }
             List<MatchInfoBase> matches = new ArrayList<>();
             matches.addAll(AclServiceUtils.buildDhcpV6Matches(AclConstants.DHCP_CLIENT_PORT_IPV6,
                 AclConstants.DHCP_SERVER_PORT_IPV6, lportTag, serviceMode));
-            matches.add(new MatchEthernetSource(aapMac));
+            matches.add(new MatchEthernetSource(aap.getMacAddress()));
 
-            String flowName = "Egress_DHCP_Client_v6" + "_" + dpId + "_" + lportTag + "_" + aapMac.getValue()
-                                    + "_Permit_";
+            String flowName = "Egress_DHCP_Client_v6" + "_" + dpId + "_" + lportTag + "_"
+                    + aap.getMacAddress().getValue() + "_Permit_";
             syncFlow(dpId, getAclAntiSpoofingTable(), flowName, AclConstants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY,
                     "ACL", 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
         }
index 5e65973d0e01330e4206b5cf2d22664d1129f7c7..c73eeb1e0e177891ce28e48d8902a2e5c61a825c 100644 (file)
@@ -119,7 +119,7 @@ public class IngressAclServiceImpl extends AbstractAclServiceImpl {
     }
 
     @Override
-    protected void programAntiSpoofingRules(AclInterface port, String dhcpMacAddress,
+    protected void programAntiSpoofingRules(AclInterface port,
             List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove) {
         LOG.info("{} programAntiSpoofingRules for port {}, AAPs={}, action={}, addOrRemove={}", this.directionString,
                 port.getInterfaceId(), allowedAddresses, action, addOrRemove);
@@ -127,10 +127,8 @@ public class IngressAclServiceImpl extends AbstractAclServiceImpl {
         BigInteger dpid = port.getDpId();
         int lportTag = port.getLPortTag();
         if (action == Action.ADD || action == Action.REMOVE) {
-            ingressAclDhcpAllowServerTraffic(dpid, dhcpMacAddress, lportTag, addOrRemove,
-                    AclConstants.PROTO_PREFIX_MATCH_PRIORITY);
-            ingressAclDhcpv6AllowServerTraffic(dpid, dhcpMacAddress, lportTag, addOrRemove,
-                    AclConstants.PROTO_PREFIX_MATCH_PRIORITY);
+            ingressAclDhcpAllowServerTraffic(dpid, lportTag, addOrRemove, AclConstants.PROTO_PREFIX_MATCH_PRIORITY);
+            ingressAclDhcpv6AllowServerTraffic(dpid, lportTag, addOrRemove, AclConstants.PROTO_PREFIX_MATCH_PRIORITY);
             ingressAclIcmpv6AllowedTraffic(dpid, lportTag, addOrRemove);
 
             programArpRule(dpid, lportTag, addOrRemove);
@@ -160,13 +158,6 @@ public class IngressAclServiceImpl extends AbstractAclServiceImpl {
         }
     }
 
-    @Override
-    protected void updateArpForAllowedAddressPairs(BigInteger dpId, int lportTag, List<AllowedAddressPairs> deletedAAP,
-            List<AllowedAddressPairs> addedAAP) {
-        // Nothing to do for port update as ingress ARP flow is based only on lportTag
-
-    }
-
     @Override
     protected void programRemoteAclTableFlow(BigInteger dpId, Integer aclTag, AllowedAddressPairs aap,
             int addOrRemove) {
@@ -185,18 +176,17 @@ public class IngressAclServiceImpl extends AbstractAclServiceImpl {
      * allowed.
      *
      * @param dpId the dpid
-     * @param dhcpMacAddress the DHCP server mac address
      * @param lportTag the lport tag
      * @param addOrRemove is write or delete
      * @param protoPortMatchPriority the priority
      */
-    protected void ingressAclDhcpAllowServerTraffic(BigInteger dpId, String dhcpMacAddress, int lportTag,
-            int addOrRemove, int protoPortMatchPriority) {
+    protected void ingressAclDhcpAllowServerTraffic(BigInteger dpId, int lportTag, int addOrRemove,
+            int protoPortMatchPriority) {
         final List<MatchInfoBase> matches = AclServiceUtils.buildDhcpMatches(AclConstants.DHCP_SERVER_PORT_IPV4,
                 AclConstants.DHCP_CLIENT_PORT_IPV4, lportTag, serviceMode);
         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
 
-        String flowName = "Ingress_DHCP_Server_v4" + dpId + "_" + lportTag + "_" + dhcpMacAddress + "_Permit_";
+        String flowName = "Ingress_DHCP_Server_v4" + dpId + "_" + lportTag + "_Permit_";
         syncFlow(dpId, getAclAntiSpoofingTable(), flowName, AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY, "ACL", 0, 0,
                 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
     }
@@ -206,19 +196,17 @@ public class IngressAclServiceImpl extends AbstractAclServiceImpl {
      * allowed.
      *
      * @param dpId the dpid
-     * @param dhcpMacAddress the DHCP server mac address
      * @param lportTag the lport tag
      * @param addOrRemove is write or delete
      * @param protoPortMatchPriority the priority
      */
-    protected void ingressAclDhcpv6AllowServerTraffic(BigInteger dpId, String dhcpMacAddress, int lportTag,
-            int addOrRemove, Integer protoPortMatchPriority) {
+    protected void ingressAclDhcpv6AllowServerTraffic(BigInteger dpId, int lportTag, int addOrRemove,
+            Integer protoPortMatchPriority) {
         final List<MatchInfoBase> matches = AclServiceUtils.buildDhcpV6Matches(AclConstants.DHCP_SERVER_PORT_IPV6,
                 AclConstants.DHCP_CLIENT_PORT_IPV6, lportTag, serviceMode);
         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
 
-        String flowName =
-                "Ingress_DHCP_Server_v6" + "_" + dpId + "_" + lportTag + "_" + "_" + dhcpMacAddress + "_Permit_";
+        String flowName = "Ingress_DHCP_Server_v6" + "_" + dpId + "_" + lportTag + "_Permit_";
         syncFlow(dpId, getAclAntiSpoofingTable(), flowName, AclConstants.PROTO_DHCP_SERVER_MATCH_PRIORITY, "ACL", 0, 0,
                 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
     }
index eb3241fd959688168385a2e5958d483fb2830c2b..4f8b7c5a68a316861d5bda4b7ea8c4d5114846a1 100644 (file)
@@ -13,6 +13,8 @@ import com.google.common.collect.Lists;
 import com.google.common.net.InetAddresses;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -1457,4 +1459,39 @@ public final class AclServiceUtils {
         return instructions;
     }
 
+    public static List<AllowedAddressPairs> excludeMulticastAAPs(List<AllowedAddressPairs> allowedAddresses) {
+        List<AllowedAddressPairs> filteredAAPs = new ArrayList<>();
+        for (AllowedAddressPairs allowedAddress : allowedAddresses) {
+            InetAddress inetAddr = getInetAddress(allowedAddress.getIpAddress());
+            if (inetAddr != null && !inetAddr.isMulticastAddress()) {
+                filteredAAPs.add(allowedAddress);
+            }
+        }
+        return filteredAAPs;
+    }
+
+    private static InetAddress getInetAddress(IpPrefixOrAddress ipPrefixOrAddress) {
+        InetAddress inetAddress = null;
+        String addr = null;
+
+        IpPrefix ipPrefix = ipPrefixOrAddress.getIpPrefix();
+        if (ipPrefix != null) {
+            addr = String.valueOf(ipPrefix.getValue()).split("/")[0];
+        } else {
+            IpAddress ipAddress = ipPrefixOrAddress.getIpAddress();
+            if (ipAddress == null) {
+                LOG.error("Invalid address : {}", ipPrefixOrAddress);
+                return null;
+            } else {
+                addr = String.valueOf(ipAddress.getValue());
+            }
+        }
+        try {
+            inetAddress = InetAddress.getByName(addr);
+        } catch (UnknownHostException e) {
+            LOG.error("Invalid address : {}", addr, e.getMessage());
+            return null;
+        }
+        return inetAddress;
+    }
 }
diff --git a/aclservice/impl/src/test/java/org/opendaylight/netvirt/aclservice/utils/AclServiceUtilsTest.java b/aclservice/impl/src/test/java/org/opendaylight/netvirt/aclservice/utils/AclServiceUtilsTest.java
new file mode 100644 (file)
index 0000000..6b13b26
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netvirt.aclservice.utils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
+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.AllowedAddressPairsBuilder;
+
+/**
+ * Unit tests for AclServiceUtils.
+ *
+ */
+public class AclServiceUtilsTest {
+
+    @Test
+    public void testExcludeMulticastAAPs() {
+        List<AllowedAddressPairs> inputAAPs = new ArrayList<>();
+        buildInputAAP(inputAAPs, "1.1.1.1/32");// non-multicast Ipv4Prefix
+        buildInputAAP(inputAAPs, "2.2.2.2");// non-multicast Ipv4Address
+        buildInputAAP(inputAAPs, "2001:db8:85a3:0:0:8a2e:370:7334"); // non-multicast Ipv6Address
+        buildInputAAP(inputAAPs, "2002:db8:85a3::8a2e:370:7334/8"); // non-multicast Ipv6Prefix
+
+        List<AllowedAddressPairs> filteredAAPs = AclServiceUtils.excludeMulticastAAPs(inputAAPs);
+        assertNotNull(filteredAAPs);
+        assertEquals(inputAAPs, filteredAAPs);
+        inputAAPs.clear();
+
+        buildInputAAP(inputAAPs, "224.0.0.0/24");// multicast Ipv4Prefix
+        buildInputAAP(inputAAPs, "224.4.2.2");// multicast Ipv4Address
+        buildInputAAP(inputAAPs, "FF01:0:0:0:0:0:0:1"); // multicast Ipv6Address
+        buildInputAAP(inputAAPs, "FF01::DB8:0:0/96"); // multicast Ipv6Prefix
+
+        filteredAAPs = AclServiceUtils.excludeMulticastAAPs(inputAAPs);
+        assertNotNull(filteredAAPs);
+        assertEquals(0, filteredAAPs.size());
+        inputAAPs.clear();
+
+        buildInputAAP(inputAAPs, "224.4.2.2");// multicast Ipv4Address
+        buildInputAAP(inputAAPs, "3.3.3.3");// non-multicast Ipv4Address
+        buildInputAAP(inputAAPs, "2001:db8:85a3:0:0:8a2e:370:7335"); // non-multicast Ipv6Address
+        buildInputAAP(inputAAPs, "FF01:0:0:0:0:0:0:2"); // multicast Ipv6Address
+
+        List<AllowedAddressPairs> tempAAPs = new ArrayList<>();
+        tempAAPs.add(buildAAp("3.3.3.3"));
+        tempAAPs.add(buildAAp("2001:db8:85a3:0:0:8a2e:370:7335"));
+
+        filteredAAPs = AclServiceUtils.excludeMulticastAAPs(inputAAPs);
+        assertNotNull(filteredAAPs);
+        assertEquals(2, filteredAAPs.size());
+        assertEquals(tempAAPs, filteredAAPs);
+        inputAAPs.clear();
+    }
+
+    private void buildInputAAP(List<AllowedAddressPairs> inputAAPs, String addr) {
+        inputAAPs.add(buildAAp(addr));
+    }
+
+    private AllowedAddressPairs buildAAp(String addr) {
+        AllowedAddressPairsBuilder aapb = new AllowedAddressPairsBuilder();
+        aapb.setIpAddress(new IpPrefixOrAddress(addr.toCharArray()));
+        aapb.setMacAddress(new MacAddress("AA:BB:CC:DD:EE:FF"));
+        return aapb.build();
+    }
+}