From: Somashekar Byrappa Date: Thu, 22 Feb 2018 15:07:28 +0000 (+0530) Subject: ACL: Handle AAP update X-Git-Tag: release/oxygen~24 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F98%2F68498%2F2;p=netvirt.git ACL: Handle AAP update 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 --- diff --git a/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/AbstractAclServiceImpl.java b/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/AbstractAclServiceImpl.java index f4c4d49e2f..3b220a8d02 100644 --- a/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/AbstractAclServiceImpl.java +++ b/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/AbstractAclServiceImpl.java @@ -185,7 +185,6 @@ public abstract class AbstractAclServiceImpl implements AclServiceListener { } private void processInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) { - BigInteger dpId = portAfter.getDpId(); List addedAaps = AclServiceUtils .getUpdatedAllowedAddressPairs(portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs()); List 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 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 deletedAAP, List addedAAP); + protected abstract void programAntiSpoofingRules(AclInterface port, List allowedAddresses, + Action action, int addOrRemove); /** * Programs broadcast rules. diff --git a/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/EgressAclServiceImpl.java b/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/EgressAclServiceImpl.java index d17e7415c9..4aa4881d2f 100644 --- a/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/EgressAclServiceImpl.java +++ b/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/EgressAclServiceImpl.java @@ -112,35 +112,25 @@ public class EgressAclServiceImpl extends AbstractAclServiceImpl { } @Override - protected void programAntiSpoofingRules(AclInterface port, String dhcpMacAddress, - List allowedAddresses, Action action, int addOrRemove) { + protected void programAntiSpoofingRules(AclInterface port, List 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 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 filteredAAPs = AclServiceUtils.excludeMulticastAAPs(allowedAddresses); - @Override - protected void updateArpForAllowedAddressPairs(BigInteger dpId, int lportTag, List deletedAAP, - List 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 aaps, int lportTag, int addOrRemove) { - for (AllowedAddressPairs aap : aaps) { + List 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 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 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 aapMacs, int lportTag, - int addOrRemove) { + private void egressAclDhcpAllowClientTraffic(BigInteger dpId, List allowedAddresses, + int lportTag, int addOrRemove) { List instructions = getDispatcherTableResubmitInstructions(); - for (MacAddress aapMac : aapMacs) { + for (AllowedAddressPairs aap : allowedAddresses) { + if (!AclServiceUtils.isIPv4Address(aap)) { + continue; + } List 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 aapMacs, int lportTag, - int addOrRemove) { + private void egressAclDhcpv6AllowClientTraffic(BigInteger dpId, List allowedAddresses, + int lportTag, int addOrRemove) { List instructions = getDispatcherTableResubmitInstructions(); - for (MacAddress aapMac : aapMacs) { + for (AllowedAddressPairs aap : allowedAddresses) { + if (AclServiceUtils.isIPv4Address(aap)) { + continue; + } List 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); } diff --git a/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/IngressAclServiceImpl.java b/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/IngressAclServiceImpl.java index 5e65973d0e..c73eeb1e0e 100644 --- a/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/IngressAclServiceImpl.java +++ b/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/IngressAclServiceImpl.java @@ -119,7 +119,7 @@ public class IngressAclServiceImpl extends AbstractAclServiceImpl { } @Override - protected void programAntiSpoofingRules(AclInterface port, String dhcpMacAddress, + protected void programAntiSpoofingRules(AclInterface port, List 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 deletedAAP, - List 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 matches = AclServiceUtils.buildDhcpMatches(AclConstants.DHCP_SERVER_PORT_IPV4, AclConstants.DHCP_CLIENT_PORT_IPV4, lportTag, serviceMode); List 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 matches = AclServiceUtils.buildDhcpV6Matches(AclConstants.DHCP_SERVER_PORT_IPV6, AclConstants.DHCP_CLIENT_PORT_IPV6, lportTag, serviceMode); List 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); } diff --git a/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/utils/AclServiceUtils.java b/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/utils/AclServiceUtils.java index eb3241fd95..4f8b7c5a68 100644 --- a/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/utils/AclServiceUtils.java +++ b/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/utils/AclServiceUtils.java @@ -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 excludeMulticastAAPs(List allowedAddresses) { + List 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 index 0000000000..6b13b2620a --- /dev/null +++ b/aclservice/impl/src/test/java/org/opendaylight/netvirt/aclservice/utils/AclServiceUtilsTest.java @@ -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 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 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 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 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(); + } +}