X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=vpnservice%2Faclservice%2Fimpl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetvirt%2Faclservice%2FAbstractIngressAclServiceImpl.java;h=2960991da63832c0b51c706bba9cebfbc8da5876;hb=a6b0153d497356daa7a9f9ad91076374535a1d9a;hp=4b5744c2cfec2dbc633f87c15c9b13e24264e1ae;hpb=560ca5aaae7804dbb8b5e168abdc1d85237941ef;p=netvirt.git diff --git a/vpnservice/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/AbstractIngressAclServiceImpl.java b/vpnservice/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/AbstractIngressAclServiceImpl.java index 4b5744c2cf..2960991da6 100644 --- a/vpnservice/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/AbstractIngressAclServiceImpl.java +++ b/vpnservice/aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/AbstractIngressAclServiceImpl.java @@ -7,23 +7,32 @@ */ package org.opendaylight.netvirt.aclservice; +import com.google.common.util.concurrent.ListenableFuture; import java.math.BigInteger; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator; import org.opendaylight.genius.mdsalutil.ActionInfo; import org.opendaylight.genius.mdsalutil.InstructionInfo; import org.opendaylight.genius.mdsalutil.MDSALUtil; -import org.opendaylight.genius.mdsalutil.MatchFieldType; -import org.opendaylight.genius.mdsalutil.MatchInfo; import org.opendaylight.genius.mdsalutil.MatchInfoBase; +import org.opendaylight.genius.mdsalutil.MetaDataUtil; import org.opendaylight.genius.mdsalutil.NwConstants; +import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable; +import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata; import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager; +import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType; +import org.opendaylight.genius.utils.ServiceIndex; import org.opendaylight.netvirt.aclservice.api.AclServiceManager.Action; +import org.opendaylight.netvirt.aclservice.api.utils.AclInterface; import org.opendaylight.netvirt.aclservice.utils.AclConstants; +import org.opendaylight.netvirt.aclservice.utils.AclDataUtil; import org.opendaylight.netvirt.aclservice.utils.AclServiceOFFlowBuilder; 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; @@ -35,8 +44,10 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.cont import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionIngress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -59,42 +70,85 @@ public abstract class AbstractIngressAclServiceImpl extends AbstractAclServiceIm * * @param dataBroker the data broker instance. * @param mdsalManager the mdsal manager. + * @param aclDataUtil + * the acl data util. + * @param aclServiceUtils + * the acl service util. */ - public AbstractIngressAclServiceImpl(DataBroker dataBroker, IMdsalApiManager mdsalManager) { + public AbstractIngressAclServiceImpl(DataBroker dataBroker, IMdsalApiManager mdsalManager, AclDataUtil aclDataUtil, + AclServiceUtils aclServiceUtils) { // Service mode is w.rt. switch - super(ServiceModeEgress.class, dataBroker, mdsalManager); + super(ServiceModeEgress.class, dataBroker, mdsalManager, aclDataUtil, aclServiceUtils); } /** * Bind service. * - * @param interfaceName the interface name + * @param aclInterface the acl interface */ @Override - protected void bindService(String interfaceName) { - int flowPriority = AclConstants.INGRESS_ACL_DEFAULT_FLOW_PRIORITY; - - int instructionKey = 0; - List instructions = new ArrayList<>(); - instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.EGRESS_ACL_TABLE, ++instructionKey)); - BoundServices serviceInfo = AclServiceUtils.getBoundServices( - String.format("%s.%s.%s", "vpn", "ingressacl", interfaceName), NwConstants.EGRESS_ACL_SERVICE_INDEX, - flowPriority, AclConstants.COOKIE_ACL_BASE, instructions); - InstanceIdentifier path = AclServiceUtils.buildServiceId(interfaceName, - NwConstants.EGRESS_ACL_SERVICE_INDEX, ServiceModeEgress.class); - MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, path, serviceInfo); + public void bindService(AclInterface aclInterface) { + String interfaceName = aclInterface.getInterfaceId(); + DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance(); + dataStoreCoordinator.enqueueJob(interfaceName, + () -> { + int instructionKey = 0; + List instructions = new ArrayList<>(); + Long vpnId = aclInterface.getVpnId(); + if (vpnId != null) { + instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(MetaDataUtil.getVpnIdMetadata(vpnId), + MetaDataUtil.METADATA_MASK_VRFID, ++instructionKey)); + LOG.debug("Binding ACL service for interface {} with vpnId {}", interfaceName, vpnId); + } else { + Long elanTag = aclInterface.getElanId(); + instructions.add( + MDSALUtil.buildAndGetWriteMetadaInstruction(MetaDataUtil.getElanTagMetadata(elanTag), + MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey)); + LOG.debug("Binding ACL service for interface {} with ElanTag {}", interfaceName, elanTag); + } + instructions.add( + MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.EGRESS_ACL_TABLE, ++instructionKey)); + int flowPriority = AclConstants.INGRESS_ACL_DEFAULT_FLOW_PRIORITY; + short serviceIndex = ServiceIndex.getIndex(NwConstants.EGRESS_ACL_SERVICE_NAME, + NwConstants.EGRESS_ACL_SERVICE_INDEX); + BoundServices serviceInfo = AclServiceUtils.getBoundServices( + String.format("%s.%s.%s", "acl", "ingressacl", interfaceName), serviceIndex, flowPriority, + AclConstants.COOKIE_ACL_BASE, instructions); + InstanceIdentifier path = AclServiceUtils.buildServiceId(interfaceName, + ServiceIndex.getIndex(NwConstants.EGRESS_ACL_SERVICE_NAME, + NwConstants.EGRESS_ACL_SERVICE_INDEX), ServiceModeEgress.class); + + WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction(); + writeTxn.put(LogicalDatastoreType.CONFIGURATION, path, serviceInfo, + WriteTransaction.CREATE_MISSING_PARENTS); + + return Collections.singletonList(writeTxn.submit()); + }); } /** * Unbind service. * - * @param interfaceName the interface name + * @param aclInterface the acl interface */ @Override - protected void unbindService(String interfaceName) { + protected void unbindService(AclInterface aclInterface) { + String interfaceName = aclInterface.getInterfaceId(); InstanceIdentifier path = AclServiceUtils.buildServiceId(interfaceName, - NwConstants.EGRESS_ACL_SERVICE_INDEX, ServiceModeEgress.class); - MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, path); + ServiceIndex.getIndex(NwConstants.EGRESS_ACL_SERVICE_NAME, NwConstants.EGRESS_ACL_SERVICE_INDEX), + ServiceModeEgress.class); + + DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance(); + LOG.debug("UnBinding ACL service for interface {}", interfaceName); + dataStoreCoordinator.enqueueJob(interfaceName, + () -> { + WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction(); + writeTxn.delete(LogicalDatastoreType.CONFIGURATION, path); + + List> futures = new ArrayList<>(); + futures.add(writeTxn.submit()); + return futures; + }); } /** @@ -111,30 +165,42 @@ public abstract class AbstractIngressAclServiceImpl extends AbstractAclServiceIm List allowedAddresses, int lportTag, String portId, Action action, int addOrRemove); @Override - protected void programGeneralFixedRules(BigInteger dpid, String dhcpMacAddress, - List allowedAddresses, int lportTag, Action action, int addOrRemove) { - LOG.info("programFixedRules : adding default rules."); + protected void programGeneralFixedRules(AclInterface port, String dhcpMacAddress, + List allowedAddresses, Action action, int addOrRemove) { + LOG.info("programFixedRules : {} default rules.", action == Action.ADD ? "adding" : "removing"); + 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); ingressAclIcmpv6AllowedTraffic(dpid, lportTag, addOrRemove); + + programArpRule(dpid, lportTag, addOrRemove); + programIpv4BroadcastRule(port, addOrRemove); } - programArpRule(dpid, lportTag, addOrRemove); } @Override - protected boolean programAclRules(List aclUuidList, BigInteger dpId, int lportTag, int addOrRemove, String - portId) { + 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 boolean programAclRules(AclInterface port, List aclUuidList,int addOrRemove) { + BigInteger dpId = port.getDpId(); + LOG.debug("Applying custom rules on DpId {}, lportTag {}", dpId, port.getLPortTag()); if (aclUuidList == null || dpId == null) { LOG.warn("one of the ingress acl parameters can not be null. sg {}, dpId {}", aclUuidList, dpId); return false; } - for (Uuid sgUuid :aclUuidList ) { + for (Uuid sgUuid :aclUuidList) { Acl acl = AclServiceUtils.getAcl(dataBroker, sgUuid.getValue()); if (null == acl) { LOG.warn("The ACL is empty"); @@ -143,40 +209,72 @@ public abstract class AbstractIngressAclServiceImpl extends AbstractAclServiceIm AccessListEntries accessListEntries = acl.getAccessListEntries(); List aceList = accessListEntries.getAce(); for (Ace ace : aceList) { - programAceRule(dpId, lportTag, addOrRemove, ace, portId, null); + programAceRule(port, addOrRemove, acl.getAclName(), ace, null); } } return true; } @Override - protected void programAceRule(BigInteger dpId, int lportTag, int addOrRemove, Ace ace, String portId, - List syncAllowedAddresses) { + protected void programAceRule(AclInterface port, int addOrRemove, String aclName, Ace ace, + List syncAllowedAddresses) { SecurityRuleAttr aceAttr = AclServiceUtils.getAccesssListAttributes(ace); if (!aceAttr.getDirection().equals(DirectionIngress.class)) { return; } Matches matches = ace.getMatches(); AceType aceType = matches.getAceType(); - Map> flowMap = null; + Map> flowMap = null; if (aceType instanceof AceIp) { flowMap = AclServiceOFFlowBuilder.programIpFlow(matches); if (syncAllowedAddresses != null) { flowMap = AclServiceUtils.getFlowForAllowedAddresses(syncAllowedAddresses, flowMap, true); } else if (aceAttr.getRemoteGroupId() != null) { - flowMap = AclServiceUtils.getFlowForRemoteAcl(aceAttr.getRemoteGroupId(), portId, flowMap, - true); + flowMap = aclServiceUtils.getFlowForRemoteAcl(port, aceAttr.getRemoteGroupId(), port.getInterfaceId(), + flowMap, true); } } + int lportTag = port.getLPortTag(); if (null == flowMap) { LOG.error("Failed to apply ACL {} lportTag {}", ace.getKey(), lportTag); return; } - for ( String flowName : flowMap.keySet()) { - flowName = syncSpecificAclFlow(dpId, lportTag, addOrRemove, ace, portId, flowMap, flowName); + for (String flowName : flowMap.keySet()) { + syncSpecificAclFlow(port.getDpId(), lportTag, addOrRemove, ace, port.getInterfaceId(), flowMap, flowName); } } + @Override + protected void updateRemoteAclTableForPort(AclInterface port, Uuid acl, int addOrRemove, + AllowedAddressPairs ip, BigInteger aclId, BigInteger dpId) { + Long elanTag = port.getElanId(); + Long vpnId = port.getVpnId(); + List flowMatches = new ArrayList<>(); + flowMatches.addAll(AclServiceUtils.buildIpAndSrcServiceMatch(elanTag, ip, dataBroker, vpnId)); + + List instructions = new ArrayList<>(); + + InstructionWriteMetadata writeMetatdata = + new InstructionWriteMetadata(AclServiceUtils.getAclIdMetadata(aclId), + MetaDataUtil.METADATA_MASK_REMOTE_ACL_ID); + instructions.add(writeMetatdata); + instructions.add(new InstructionGotoTable(getIngressAclFilterTable())); + + Long serviceTag = vpnId != null ? vpnId : elanTag; + String flowNameAdded = "Acl_Filter_Ingress_" + new String(ip.getIpAddress().getValue()) + "_" + serviceTag; + + syncFlow(dpId, getIngressAclRemoteAclTable(), flowNameAdded, AclConstants.NO_PRIORITY, "ACL", 0, 0, + AclConstants.COOKIE_ACL_BASE, flowMatches, instructions, addOrRemove); + } + + protected short getIngressAclFilterTable() { + return NwConstants.EGRESS_ACL_FILTER_TABLE; + } + + protected short getIngressAclRemoteAclTable() { + return NwConstants.EGRESS_ACL_REMOTE_ACL_TABLE; + } + protected abstract String syncSpecificAclFlow(BigInteger dpId, int lportTag, int addOrRemove, Ace ace, String portId, Map> flowMap, String flowName); @@ -193,7 +291,7 @@ public abstract class AbstractIngressAclServiceImpl extends AbstractAclServiceIm protected void ingressAclDhcpAllowServerTraffic(BigInteger dpId, String dhcpMacAddress, int lportTag, int addOrRemove, int protoPortMatchPriority) { final List matches = AclServiceUtils.buildDhcpMatches(AclConstants.DHCP_SERVER_PORT_IPV4, - AclConstants.DHCP_CLIENT_PORT_IPV4, lportTag); + AclConstants.DHCP_CLIENT_PORT_IPV4, lportTag, ServiceModeIngress.class); List actionsInfos = new ArrayList<>(); List instructions = getDispatcherTableResubmitInstructions(actionsInfos); @@ -216,7 +314,7 @@ public abstract class AbstractIngressAclServiceImpl extends AbstractAclServiceIm protected void ingressAclDhcpv6AllowServerTraffic(BigInteger dpId, String dhcpMacAddress, int lportTag, int addOrRemove, Integer protoPortMatchPriority) { final List matches = AclServiceUtils.buildDhcpV6Matches(AclConstants.DHCP_SERVER_PORT_IPV6, - AclConstants.DHCP_CLIENT_PORT_IPV6, lportTag); + AclConstants.DHCP_CLIENT_PORT_IPV6, lportTag, ServiceModeIngress.class); List actionsInfos = new ArrayList<>(); List instructions = getDispatcherTableResubmitInstructions(actionsInfos); @@ -240,7 +338,7 @@ public abstract class AbstractIngressAclServiceImpl extends AbstractAclServiceIm // Allow ICMPv6 Multicast Listener Query packets. List matches = AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_MLD_QUERY, - 0, lportTag); + 0, lportTag, ServiceModeIngress.class); String flowName = "Ingress_ICMPv6" + "_" + dpId + "_" + lportTag + "_" + AclConstants.ICMPV6_TYPE_MLD_QUERY + "_Permit_"; @@ -248,7 +346,8 @@ public abstract class AbstractIngressAclServiceImpl extends AbstractAclServiceIm 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove); // Allow ICMPv6 Neighbor Solicitation packets. - matches = AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_NS, 0, lportTag); + matches = AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_NS, 0, lportTag, + ServiceModeIngress.class); flowName = "Ingress_ICMPv6" + "_" + dpId + "_" + lportTag + "_" + AclConstants.ICMPV6_TYPE_NS + "_Permit_"; @@ -256,7 +355,8 @@ public abstract class AbstractIngressAclServiceImpl extends AbstractAclServiceIm 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove); // Allow ICMPv6 Neighbor Advertisement packets. - matches = AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_NA, 0, lportTag); + matches = AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_NA, 0, lportTag, + ServiceModeIngress.class); flowName = "Ingress_ICMPv6" + "_" + dpId + "_" + lportTag + "_" + AclConstants.ICMPV6_TYPE_NA + "_Permit_"; @@ -272,14 +372,60 @@ public abstract class AbstractIngressAclServiceImpl extends AbstractAclServiceIm * @param addOrRemove whether to add or remove the flow */ protected void programArpRule(BigInteger dpId, int lportTag, int addOrRemove) { - List matches = new ArrayList<>(); - matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] {NwConstants.ETHTYPE_ARP})); - matches.add(AclServiceUtils.buildLPortTagMatch(lportTag)); - + List matches = new ArrayList<>(); + matches.add(MatchEthernetType.ARP); + matches.add(buildLPortTagMatch(lportTag)); List instructions = getDispatcherTableResubmitInstructions(new ArrayList<>()); + LOG.debug(addOrRemove == NwConstants.DEL_FLOW ? "Deleting " : "Adding " + "ARP Rule on DPID {}, " + + "lportTag {}", dpId, lportTag); String flowName = "Ingress_ARP_" + dpId + "_" + lportTag; syncFlow(dpId, NwConstants.EGRESS_ACL_TABLE, flowName, AclConstants.PROTO_ARP_TRAFFIC_MATCH_PRIORITY, "ACL", 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove); } + + + /** + * Programs broadcast rules. + * + * @param port the Acl Interface port + * @param addOrRemove whether to delete or add flow + */ + @Override + protected void programBroadcastRules(AclInterface port, int addOrRemove) { + programIpv4BroadcastRule(port, addOrRemove); + } + + /** + * Programs IPv4 broadcast rules. + * + * @param port the Acl Interface port + * @param addOrRemove whether to delete or add flow + */ + private void programIpv4BroadcastRule(AclInterface port, int addOrRemove) { + BigInteger dpId = port.getDpId(); + int lportTag = port.getLPortTag(); + MatchInfoBase lportMatchInfo = buildLPortTagMatch(lportTag); + List cidrs = port.getSubnetIpPrefixes(); + if (cidrs != null) { + List broadcastAddresses = AclServiceUtils.getIpBroadcastAddresses(cidrs); + for (String broadcastAddress : broadcastAddresses) { + List matches = + AclServiceUtils.buildBroadcastIpV4Matches(broadcastAddress); + matches.add(lportMatchInfo); + List instructions = new ArrayList<>(); + instructions.add(new InstructionGotoTable(NwConstants.EGRESS_ACL_REMOTE_ACL_TABLE)); + String flowName = "Ingress_v4_Broadcast_" + dpId + "_" + lportTag + "_" + broadcastAddress + "_Permit"; + syncFlow(dpId, NwConstants.EGRESS_ACL_TABLE, flowName, + AclConstants.PROTO_MATCH_PRIORITY, "ACL", 0, 0, AclConstants.COOKIE_ACL_BASE, matches, + instructions, addOrRemove); + } + } else { + LOG.error("IP Broadcast CIDRs are missing for port {}", port.getInterfaceId()); + } + } + + protected MatchInfoBase buildLPortTagMatch(int lportTag) { + return AclServiceUtils.buildLPortTagMatch(lportTag, ServiceModeIngress.class); + } }