General clean-ups
[netvirt.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / netvirt / openstack / netvirt / providers / openflow13 / services / EgressAclService.java
index 9568f49feab16a37bac0eea45672c350403fd211..a8ef5445f687c03a14b76dc809abfa0ff89de545 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 - 2016 Red Hat, Inc. and others. All rights reserved.
+ * Copyright © 2014, 2017 Red Hat, Inc. 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,
@@ -8,14 +8,21 @@
 
 package org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.services;
 
-import com.google.common.collect.Lists;
-
-import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
+import java.math.BigInteger;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 import org.opendaylight.netvirt.openstack.netvirt.api.Constants;
 import org.opendaylight.netvirt.openstack.netvirt.api.EgressAclProvider;
+import org.opendaylight.netvirt.openstack.netvirt.api.LearnConstants;
 import org.opendaylight.netvirt.openstack.netvirt.api.SecurityGroupCacheManger;
 import org.opendaylight.netvirt.openstack.netvirt.api.SecurityServicesManager;
 import org.opendaylight.netvirt.openstack.netvirt.providers.ConfigInterface;
+import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
 import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.Service;
 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityGroup;
 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityRule;
@@ -37,19 +44,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv6MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
 public class EgressAclService extends AbstractServiceInstance implements EgressAclProvider, ConfigInterface {
 
     private static final Logger LOG = LoggerFactory.getLogger(EgressAclService.class);
@@ -75,7 +78,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
 
     @Override
     public void programPortSecurityGroup(Long dpid, String segmentationId, String attachedMac, long localPort,
-                                       NeutronSecurityGroup securityGroup, String portUuid, boolean write) {
+                                       NeutronSecurityGroup securityGroup, String portUuid, NodeId nodeId, boolean write) {
 
         LOG.trace("programPortSecurityGroup: neutronSecurityGroup: {} ", securityGroup);
         if (securityGroup == null || getSecurityRulesforGroup(securityGroup) == null) {
@@ -114,7 +117,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
                                                     localPort, portSecurityRule, vmIp, write);
                         }
                         if (write) {
-                            securityGroupCacheManger.addToCache(portSecurityRule.getSecurityRemoteGroupID(), portUuid);
+                            securityGroupCacheManger.addToCache(portSecurityRule.getSecurityRemoteGroupID(), portUuid, nodeId);
                         } else {
                             securityGroupCacheManger.removeFromCache(portSecurityRule.getSecurityRemoteGroupID(),
                                                                      portUuid);
@@ -165,34 +168,53 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
             /* TODO Rework on the priority values */
             egressAclIp(dpid, isIpv6, segmentationId, attachedMac,
                 portSecurityRule, ipaddress,
-                write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
+                write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, false);
+            if(!isIpv6) {
+                portSecurityRule.setSecurityRuleProtocol(MatchUtils.TCP);
+                portSecurityRule.setSecurityRulePortMin(PORT_RANGE_MIN);
+                portSecurityRule.setSecurityRulePortMax(PORT_RANGE_MAX);
+                egressAclTcp(dpid, segmentationId, attachedMac,
+                        portSecurityRule,ipaddress, write,
+                        Constants.PROTO_PORT_MATCH_PRIORITY, false);
+                portSecurityRule.setSecurityRuleProtocol(MatchUtils.UDP);
+                egressAclUdp(dpid, segmentationId, attachedMac,
+                        portSecurityRule, ipaddress, write,
+                        Constants.PROTO_PORT_MATCH_PRIORITY, false);
+                portSecurityRule.setSecurityRuleProtocol(MatchUtils.ICMP);
+                portSecurityRule.setSecurityRulePortMin(null);
+                portSecurityRule.setSecurityRulePortMax(null);
+                egressAclIcmp(dpid, segmentationId, attachedMac,
+                        portSecurityRule, ipaddress,write,
+                        Constants.PROTO_PORT_MATCH_PRIORITY, false);
+                portSecurityRule.setSecurityRuleProtocol(null);
+            }
         } else {
-            switch (portSecurityRule.getSecurityRuleProtocol()) {
+            switch (portSecurityRule.getSecurityRuleProtocol() == null ? "" : portSecurityRule.getSecurityRuleProtocol()) {
                 case MatchUtils.TCP:
                     LOG.debug("programPortSecurityRule: Rule matching TCP", portSecurityRule);
                     egressAclTcp(dpid, segmentationId, attachedMac,
                         portSecurityRule,ipaddress, write,
-                        Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
+                        Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, false);
                     break;
                 case MatchUtils.UDP:
                     LOG.debug("programPortSecurityRule: Rule matching UDP", portSecurityRule);
                     egressAclUdp(dpid, segmentationId, attachedMac,
                         portSecurityRule, ipaddress, write,
-                        Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
+                        Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, false);
                     break;
                 case MatchUtils.ICMP:
                 case MatchUtils.ICMPV6:
                     LOG.debug("programPortSecurityRule: Rule matching ICMP", portSecurityRule);
                     egressAclIcmp(dpid, segmentationId, attachedMac,
                         portSecurityRule, ipaddress,write,
-                        Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
+                        Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, false);
                     break;
                 default:
                     LOG.info("programPortSecurityAcl: Protocol is not TCP/UDP/ICMP but other "
                             + "protocol = ", portSecurityRule.getSecurityRuleProtocol());
                     egressOtherProtocolAclHandler(dpid, segmentationId, attachedMac,
                         portSecurityRule, ipaddress, write,
-                        Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
+                        Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, isIpv6);
                     break;
             }
         }
@@ -200,36 +222,89 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
 
     private void egressOtherProtocolAclHandler(Long dpidLong, String segmentationId, String srcMac,
                                                NeutronSecurityRule portSecurityRule, String dstAddress,
-                                               boolean write, Integer priority) {
-        MatchBuilder matchBuilder = new MatchBuilder();
-        String flowId = "Egress_Other_" + segmentationId + "_" + srcMac + "_";
-        matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
-
-        short proto = 0;
-        try {
-            Integer protocol = new Integer(portSecurityRule.getSecurityRuleProtocol());
-            proto = protocol.shortValue();
-            flowId = flowId + proto;
-        } catch (NumberFormatException e) {
-            LOG.error("Protocol vlaue conversion failure", e);
-        }
-        matchBuilder = MatchUtils.createIpProtocolMatch(matchBuilder, proto);
-
-        if (null != dstAddress) {
-            flowId = flowId + dstAddress;
-            matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
-                                                         MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
-
-        } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
-            flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
-            matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
-                    new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
+                                               boolean write, Integer priority, boolean isIpv6) {
+        if(null == portSecurityRule.getSecurityRuleProtocol() || portSecurityRule.getSecurityRuleProtocol().equals(MatchUtils.ANY_PROTOCOL)) {
+            egressAclIp(dpidLong, isIpv6, segmentationId, srcMac,
+                    portSecurityRule, dstAddress,
+                    write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY - 1, true);
+            if(!isIpv6) {
+                portSecurityRule.setSecurityRuleProtocol(MatchUtils.TCP);
+                portSecurityRule.setSecurityRulePortMin(PORT_RANGE_MIN);
+                portSecurityRule.setSecurityRulePortMax(PORT_RANGE_MAX);
+                egressAclTcp(dpidLong, segmentationId, srcMac,
+                        portSecurityRule,dstAddress, write,
+                        Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, true);
+                portSecurityRule.setSecurityRuleProtocol(MatchUtils.UDP);
+                egressAclUdp(dpidLong, segmentationId, srcMac,
+                        portSecurityRule, dstAddress, write,
+                        Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, true);
+                portSecurityRule.setSecurityRulePortMin(null);
+                portSecurityRule.setSecurityRulePortMax(null);
+                portSecurityRule.setSecurityRuleProtocol(MatchUtils.ICMP);
+                egressAclIcmp(dpidLong, segmentationId, srcMac,
+                        portSecurityRule, dstAddress,write,
+                        Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, true);
+                portSecurityRule.setSecurityRuleProtocol(null);
+            }
+        } else {
+            switch (portSecurityRule.getSecurityRuleProtocol()) {
+                case MatchUtils.TCP_PROTOCOL:
+                    portSecurityRule.setSecurityRulePortMin(PORT_RANGE_MIN);
+                    portSecurityRule.setSecurityRulePortMax(PORT_RANGE_MAX);
+                    egressAclTcp(dpidLong, segmentationId, srcMac,
+                            portSecurityRule, dstAddress, write,
+                            Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, false);
+                    break;
+                case MatchUtils.UDP_PROTOCOL:
+                    portSecurityRule.setSecurityRulePortMin(PORT_RANGE_MIN);
+                    portSecurityRule.setSecurityRulePortMax(PORT_RANGE_MAX);
+                    egressAclUdp(dpidLong, segmentationId, srcMac,
+                            portSecurityRule, dstAddress, write,
+                            Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, false);
+                    break;
+                case MatchUtils.ICMP_PROTOCOL:
+                    egressAclIcmp(dpidLong, segmentationId, srcMac,
+                            portSecurityRule, dstAddress, write,
+                            Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY, false);
+                    break;
+                default:
+                    MatchBuilder matchBuilder = new MatchBuilder();
+                    String flowId = "Egress_Other_" + segmentationId + "_" + srcMac + "_";
+                    matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder, srcMac, null,
+                            MatchUtils.ETHERTYPE_IPV4);
+                    short proto = 0;
+                    try {
+                        Integer protocol = new Integer(portSecurityRule.getSecurityRuleProtocol());
+                        proto = protocol.shortValue();
+                        flowId = flowId + proto;
+                    } catch (NumberFormatException e) {
+                        LOG.error("Protocol vlaue conversion failure", e);
+                    }
+                    matchBuilder = MatchUtils.createIpProtocolAndEthMatch(matchBuilder, proto, srcMac, null);
+                    if (null != dstAddress) {
+                        flowId = flowId + dstAddress;
+                        matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
+                                MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
+                    } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
+                        flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
+                        if (isIpv6) {
+                            matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder, null,
+                                    new Ipv6Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
+                        } else {
+                            if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
+                                matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
+                                        new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
+                            }
+                        }
+                    }
+                    flowId = flowId + "_Permit";
+                    NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
+                    FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, priority, matchBuilder, getTable());
+                    addInstructionWithConntrackCommit(flowBuilder, false);
+                    syncFlow(flowBuilder, nodeBuilder, write);
+                    break;
+            }
         }
-        flowId = flowId + "_Permit";
-        NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
-        FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, priority, matchBuilder, getTable());
-        addInstructionWithConntrackCommit(flowBuilder, false);
-        syncFlow(flowBuilder ,nodeBuilder, write);
     }
 
     @Override
@@ -244,18 +319,26 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         if (securityServicesManager.isConntrackEnabled()) {
             programEgressAclFixedConntrackRule(dpid, segmentationId, localPort, attachedMac, write);
         } else {
-            // add rule to drop tcp syn packets from the vm
-            addTcpSynFlagMatchIpv4Drop(dpid, segmentationId, attachedMac, write,
-                                                         Constants.PROTO_TCP_SYN_MATCH_PRIORITY_DROP);
-            addTcpSynFlagMatchIpv6Drop(dpid, segmentationId, attachedMac, write,
-                Constants.PROTO_TCP_SYN_MATCH_PRIORITY_DROP);
+            egressVMDrop(dpid, segmentationId, attachedMac, write,Constants.PROTO_TCP_SYN_MATCH_PRIORITY_DROP);
+            egressVMRegex(dpid, segmentationId, attachedMac, write,Constants.PROTO_REG6_MATCH_PRIORITY);
         }
-        // add rule to drop the DHCP server traffic originating from the vm.
         egressAclDhcpDropServerTrafficfromVm(dpid, localPort, write,
                                              Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
         egressAclDhcpv6DropServerTrafficfromVm(dpid, localPort, write,
                                                Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
     }
+    private void egressVMRegex(Long dpidLong, String segmentationId, String srcMac,
+            boolean write, Integer priority) {
+        String flowName = "Egress_Regx_" + segmentationId + "_" + srcMac;
+        MatchBuilder matchBuilder = new MatchBuilder();
+        matchBuilder = MatchUtils.createV4EtherMatchWithoutType(matchBuilder,srcMac,null);
+        MatchUtils.addNxRegMatch(matchBuilder,
+                new MatchUtils.RegMatch(ClassifierService.REG_FIELD_6, ClassifierService.REG_VALUE_FROM_LOCAL));
+        FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
+        addPipelineInstruction(flowBuilder, null, false);
+        NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
+        syncFlow(flowBuilder, nodeBuilder, write);
+    }
 
     private void addTcpSynFlagMatchIpv4Drop(Long dpidLong, String segmentationId, String srcMac,
                                   boolean write, Integer priority) {
@@ -268,6 +351,16 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
         syncFlow(flowBuilder, nodeBuilder, write);
     }
+    private void egressVMDrop(Long dpidLong, String segmentationId, String srcMac,
+            boolean write, Integer priority) {
+        String flowName = "Egress_Drop_" + segmentationId + "_" + srcMac + "_DROP";
+        MatchBuilder matchBuilder = new MatchBuilder();
+        matchBuilder = MatchUtils.createV4EtherMatchWithoutType(matchBuilder,srcMac,null);
+        FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
+        addPipelineInstruction(flowBuilder, null, true);
+        NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
+        syncFlow(flowBuilder, nodeBuilder, write);
+    }
 
     private void addTcpSynFlagMatchIpv6Drop(Long dpidLong, String segmentationId, String srcMac,
                                         boolean write, Integer priority) {
@@ -385,11 +478,12 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
      * @param segmentationId the segementation id
      * @param srcMac the src mac address
      * @param write add or remove
+     * @param isRegMatchReq add Reg MAtch or not
      * @param protoPortMatchPriority the protocol match priority.
      */
     private void egressAclIp(Long dpidLong, boolean isIpv6, String segmentationId, String srcMac,
                              NeutronSecurityRule portSecurityRule, String srcAddress,
-                               boolean write, Integer protoPortMatchPriority ) {
+                               boolean write, Integer protoPortMatchPriority, boolean isRegMatchReq ) {
         MatchBuilder matchBuilder = new MatchBuilder();
         String flowId = "Egress_IP" + segmentationId + "_" + srcMac + "_Permit_";
         if (isIpv6) {
@@ -397,6 +491,11 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         } else {
             matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
         }
+        if (isRegMatchReq) {
+            flowId = flowId + "_regEx_";
+            MatchUtils.addNxRegMatch(matchBuilder,
+                    new MatchUtils.RegMatch(ClassifierService.REG_FIELD_6, ClassifierService.REG_VALUE_FROM_LOCAL_0));
+        }
         if (null != srcAddress) {
             flowId = flowId + srcAddress;
             if (isIpv6) {
@@ -406,6 +505,20 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
                         MatchUtils.iPv4PrefixFromIPv4Address(srcAddress),null);
             }
+        } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
+            flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
+            if (isIpv6) {
+                matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
+                        new Ipv6Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
+            } else {
+                // Fix: Bug 6473
+                // IP match removed if CIDR created as 0.0.0.0/0 in openstack security rule
+                if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
+                    matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
+                            new Ipv4Prefix(portSecurityRule
+                                           .getSecurityRuleRemoteIpPrefix()));
+                 }
+            }
         } else {
             if (isIpv6) {
                 flowId = flowId + "Ipv6";
@@ -430,11 +543,12 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
      * @param portSecurityRule the security rule in the SG
      * @param dstAddress the destination IP address
      * @param write add or delete
+     * @param isRegMatchReq add Reg MAtch or not
      * @param protoPortMatchPriority the protocol match priroty
      */
     private void egressAclTcp(Long dpidLong, String segmentationId, String srcMac,
                               NeutronSecurityRule portSecurityRule, String dstAddress,
-                              boolean write, Integer protoPortMatchPriority) {
+                              boolean write, Integer protoPortMatchPriority, boolean isRegMatchReq) {
         boolean portRange = false;
         MatchBuilder matchBuilder = new MatchBuilder();
         String flowId = "Egress_TCP_" + segmentationId + "_" + srcMac + "_";
@@ -444,6 +558,11 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         } else {
             matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
         }
+        if (isRegMatchReq) {
+            flowId = flowId + "_regEx_";
+            MatchUtils.addNxRegMatch(matchBuilder,
+                    new MatchUtils.RegMatch(ClassifierService.REG_FIELD_6, ClassifierService.REG_VALUE_FROM_LOCAL_0));
+        }
 
         /* Custom TCP Match */
         if (portSecurityRule.getSecurityRulePortMin() != null && portSecurityRule.getSecurityRulePortMax() != null) {
@@ -496,19 +615,17 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
                 MatchUtils.addLayer4MatchWithMask(matchBuilder, MatchUtils.TCP_SHORT,
                                                   0, port, portMaskMap.get(port));
                 addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
-                addTcpSynMatch(matchBuilder);
                 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(rangeflowId, protoPortMatchPriority,
                                                                       matchBuilder, getTable());
-                addInstructionWithConntrackCommit(flowBuilder, false);
+                addInstructionWithLearnConntrackCommit(portSecurityRule, flowBuilder, null, null);
                 syncFlow(flowBuilder ,nodeBuilder, write);
             }
         } else {
             flowId = flowId + "_Permit";
             addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
-            addTcpSynMatch(matchBuilder);
             FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority,
                                                                   matchBuilder, getTable());
-            addInstructionWithConntrackCommit(flowBuilder, false);
+            addInstructionWithLearnConntrackCommit(portSecurityRule, flowBuilder, null, null);
             syncFlow(flowBuilder ,nodeBuilder, write);
         }
     }
@@ -521,15 +638,15 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
 
     private void egressAclIcmp(Long dpidLong, String segmentationId, String srcMac,
             NeutronSecurityRule portSecurityRule, String dstAddress,
-            boolean write, Integer protoPortMatchPriority) {
+            boolean write, Integer protoPortMatchPriority, boolean isRegMatchReq) {
 
         boolean isIpv6 = NeutronSecurityRule.ETHERTYPE_IPV6.equals(portSecurityRule.getSecurityRuleEthertype());
         if (isIpv6) {
             egressAclIcmpV6(dpidLong, segmentationId, srcMac, portSecurityRule, dstAddress, write,
-                            protoPortMatchPriority);
+                            protoPortMatchPriority, isRegMatchReq);
         } else {
             egressAclIcmpV4(dpidLong, segmentationId, srcMac, portSecurityRule, dstAddress, write,
-                            protoPortMatchPriority);
+                            protoPortMatchPriority, isRegMatchReq);
         }
     }
 
@@ -543,13 +660,15 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
      * @param portSecurityRule the security rule in the SG
      * @param dstAddress the source IP address
      * @param write add or delete
+     * @param isRegMatchReq add Reg MAtch or not
      * @param protoPortMatchPriority the protocol match priority
      */
     private void egressAclIcmpV4(Long dpidLong, String segmentationId, String srcMac,
                                  NeutronSecurityRule portSecurityRule, String dstAddress,
-                                 boolean write, Integer protoPortMatchPriority) {
+                                 boolean write, Integer protoPortMatchPriority, boolean isRegMatchReq) {
 
         MatchBuilder matchBuilder = new MatchBuilder();
+        boolean isIcmpAll = false;
         String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_";
         matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
         /*Custom ICMP Match */
@@ -561,10 +680,16 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
                     portSecurityRule.getSecurityRulePortMin().shortValue(),
                     portSecurityRule.getSecurityRulePortMax().shortValue());
         } else {
+            isIcmpAll = true;
             /* All ICMP Match */ // We are getting from neutron NULL for both min and max
             flowId = flowId + "all" + "_" ;
             matchBuilder = MatchUtils.createICMPv4Match(matchBuilder, MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
         }
+        if (isRegMatchReq) {
+            flowId = flowId + "_regEx_";
+            MatchUtils.addNxRegMatch(matchBuilder,
+                    new MatchUtils.RegMatch(ClassifierService.REG_FIELD_6, ClassifierService.REG_VALUE_FROM_LOCAL_0));
+        }
         if (null != dstAddress) {
             flowId = flowId + dstAddress;
             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
@@ -576,12 +701,71 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
                     new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
             }
         }
-        flowId = flowId + "_Permit";
-        addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
-        FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority, matchBuilder, getTable());
-        addInstructionWithConntrackCommit(flowBuilder, false);
+        //matchBuilder = MatchUtils.createICMPv4Match(matchBuilder, portSecurityRule.getSecurityRulePortMin().shortValue(), portSecurityRule.getSecurityRulePortMax().shortValue());
+        if(isIcmpAll)
+        {
+            Map<Integer, String> map = LearnConstants.ICMP_TYPE_MAP;
+            for(Map.Entry<Integer, String> entry : map.entrySet()) {
+                Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
+                icmpv4match.setIcmpv4Type(entry.getKey().shortValue());
+                icmpv4match.setIcmpv4Code((short)0);
+                matchBuilder.setIcmpv4Match(icmpv4match.build());
+                String rangeflowId = flowId + "_" + entry.getKey() + "_" + entry.getValue();
+                addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
+                FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(rangeflowId, protoPortMatchPriority, matchBuilder, getTable());
+                addInstructionWithLearnConntrackCommit(portSecurityRule, flowBuilder, entry.getValue(), "0");
+                syncFlow(flowBuilder ,nodeBuilder, write);
+            }
+            addIcmpFlow(nodeBuilder, portSecurityRule, segmentationId, srcMac, dstAddress, write, isRegMatchReq);
+        } else {
+            flowId = flowId + "_Permit";
+            addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
+            FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority, matchBuilder, getTable());
+             String icmpType = LearnConstants.ICMP_TYPE_MAP.get(portSecurityRule.getSecurityRulePortMin());
+            if (icmpType == null){
+                icmpType = Integer.toString(portSecurityRule.getSecurityRulePortMin());
+            }
+            addInstructionWithLearnConntrackCommit(portSecurityRule, flowBuilder, icmpType,
+                    Integer.toString(portSecurityRule.getSecurityRulePortMax()));
+            syncFlow(flowBuilder ,nodeBuilder, write);
+        }
+    }
+
+    private void addIcmpFlow(NodeBuilder nodeBuilder, NeutronSecurityRule portSecurityRule, String segmentationId, String srcMac,
+            String dstAddress, boolean write, boolean isRegMatchReq){
+        MatchBuilder matchBuilder = new MatchBuilder();
+        InstructionBuilder instructionBuilder = null;
+        short learnTableId=getTable(Service.ACL_LEARN_SERVICE);
+        short resubmitId=getTable(Service.LOAD_BALANCER);
+        String flowId = "Ingress_ICMP_" + segmentationId + "_" + srcMac + "_";
+        matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
+        flowId = flowId + "all" + "_" ;
+        matchBuilder = MatchUtils.createICMPv4Match(matchBuilder, MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
+        if (null != dstAddress) {
+            flowId = flowId + dstAddress;
+            matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
+                    MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
+        } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
+            flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
+            if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
+                matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
+                    new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
+            }
+        }
+        if (isRegMatchReq) {
+            flowId = flowId + "_regEx_";
+            MatchUtils.addNxRegMatch(matchBuilder,
+                    new MatchUtils.RegMatch(ClassifierService.REG_FIELD_6, ClassifierService.REG_VALUE_FROM_LOCAL_0));
+        }
+        Icmpv4MatchBuilder icmpv4match = new Icmpv4MatchBuilder();
+        matchBuilder.setIcmpv4Match(icmpv4match.build());
+        String rangeflowId = flowId;
+        addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
+        FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(rangeflowId, Constants.PROTO_PORT_ICMP_MATCH_PRIORITY, matchBuilder, getTable());
+        addPipelineInstruction(flowBuilder, null, false);
         syncFlow(flowBuilder ,nodeBuilder, write);
+
     }
 
     /**
@@ -594,11 +778,12 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
      * @param portSecurityRule the security rule in the SG
      * @param dstAddress the source IP address
      * @param write add or delete
+     * @param isRegMatchReq add Reg MAtch or not
      * @param protoPortMatchPriority the protocol match priority
      */
     private void egressAclIcmpV6(Long dpidLong, String segmentationId, String srcMac,
                                  NeutronSecurityRule portSecurityRule, String dstAddress,
-                                 boolean write, Integer protoPortMatchPriority) {
+                                 boolean write, Integer protoPortMatchPriority, boolean isRegMatchReq) {
 
         MatchBuilder matchBuilder = new MatchBuilder();
         String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_";
@@ -617,6 +802,11 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
             flowId = flowId + "all" + "_" ;
             matchBuilder = MatchUtils.createICMPv6Match(matchBuilder, MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
         }
+        if (isRegMatchReq) {
+            flowId = flowId + "_regEx_";
+            MatchUtils.addNxRegMatch(matchBuilder,
+                    new MatchUtils.RegMatch(ClassifierService.REG_FIELD_6, ClassifierService.REG_VALUE_FROM_LOCAL_0));
+        }
         if (null != dstAddress) {
             flowId = flowId + dstAddress;
             matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
@@ -644,11 +834,12 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
      * @param portSecurityRule the security rule in the SG
      * @param dstAddress the source IP address
      * @param write add or delete
+     * @param isRegMatchReq add Reg MAtch or not
      * @param protoPortMatchPriority the protocol match priroty
      */
     private void egressAclUdp(Long dpidLong, String segmentationId, String srcMac,
                               NeutronSecurityRule portSecurityRule, String dstAddress,
-                              boolean write, Integer protoPortMatchPriority) {
+                              boolean write, Integer protoPortMatchPriority, boolean isRegMatchReq) {
         boolean portRange = false;
         MatchBuilder matchBuilder = new MatchBuilder();
         String flowId = "Egress_UDP_" + segmentationId + "_" + srcMac + "_";
@@ -658,6 +849,11 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         } else {
             matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
         }
+        if (isRegMatchReq) {
+            flowId = flowId + "_regEx_";
+            MatchUtils.addNxRegMatch(matchBuilder,
+                    new MatchUtils.RegMatch(ClassifierService.REG_FIELD_6, ClassifierService.REG_VALUE_FROM_LOCAL_0));
+        }
 
         /* Custom UDP Match */
         if (portSecurityRule.getSecurityRulePortMin() != null && portSecurityRule.getSecurityRulePortMax() != null) {
@@ -691,9 +887,11 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
                         new Ipv6Prefix(portSecurityRule
                                        .getSecurityRuleRemoteIpPrefix()));
             } else {
+                if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
                         new Ipv4Prefix(portSecurityRule
                                        .getSecurityRuleRemoteIpPrefix()));
+                }
             }
         }
         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
@@ -709,7 +907,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
                 addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
                 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(rangeflowId, protoPortMatchPriority,
                                                                       matchBuilder, getTable());
-                addInstructionWithConntrackCommit(flowBuilder, false);
+                addInstructionWithLearnConntrackCommit(portSecurityRule, flowBuilder, null, null);
                 syncFlow(flowBuilder ,nodeBuilder, write);
             }
         } else {
@@ -717,7 +915,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
             addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
             FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority,
                                                                   matchBuilder, getTable());
-            addInstructionWithConntrackCommit(flowBuilder, false);
+            addInstructionWithLearnConntrackCommit(portSecurityRule, flowBuilder, null, null);
             syncFlow(flowBuilder ,nodeBuilder, write);
         }
     }
@@ -732,7 +930,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
      */
     private void egressAclDhcpAllowClientTrafficFromVm(Long dpidLong,
                                                        boolean write, long localPort, Integer priority) {
-        String flowName = "Egress_DHCP_Client + "_Permit_";
+        String flowName = "Egress_DHCP_Client_"  + localPort + "_Permit_";
         MatchBuilder matchBuilder = new MatchBuilder();
         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
         MatchUtils.createDhcpMatch(matchBuilder, DHCP_DESTINATION_PORT, DHCP_SOURCE_PORT);
@@ -752,7 +950,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
      */
     private void egressAclDhcpv6AllowClientTrafficFromVm(Long dpidLong,
                                                          boolean write, long localPort, Integer priority) {
-        String flowName = "Egress_DHCPv6_Client + "_Permit_";
+        String flowName = "Egress_DHCPv6_Client_"  + localPort + "_Permit_";
         MatchBuilder matchBuilder = new MatchBuilder();
         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
         MatchUtils.createDhcpv6Match(matchBuilder, DHCPV6_DESTINATION_PORT, DHCPV6_SOURCE_PORT);
@@ -867,6 +1065,25 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
         }
         return addPipelineInstruction(flowBuilder,instructionBuilder, isDrop);
     }
+    private FlowBuilder addInstructionWithLearnConntrackCommit(NeutronSecurityRule portSecurityRule, FlowBuilder flowBuilder, String icmpType, String icmpCode) {
+        InstructionBuilder instructionBuilder = null;
+        short learnTableId=getTable(Service.ACL_LEARN_SERVICE);
+        short resubmitId=getTable(Service.LOAD_BALANCER);
+        if (securityServicesManager.isConntrackEnabled()) {
+            Action conntrackAction = ActionUtils.nxConntrackAction(1, 0L, 0, (short)0xff);
+            instructionBuilder = InstructionUtils
+                    .createInstructionBuilder(ActionUtils.conntrackActionBuilder(conntrackAction), 1, false);
+            return addPipelineInstruction(flowBuilder,instructionBuilder, false);
+        }
+        if (portSecurityRule.getSecurityRuleProtocol().equalsIgnoreCase(MatchUtils.TCP) || portSecurityRule.getSecurityRuleProtocol().equalsIgnoreCase(MatchUtils.TCP_PROTOCOL)) {
+            return EgressAclLearnServiceUtil.programEgressAclLearnRuleForTcp(flowBuilder,instructionBuilder,learnTableId,resubmitId);
+        } else if (portSecurityRule.getSecurityRuleProtocol().equalsIgnoreCase(MatchUtils.UDP)  || portSecurityRule.getSecurityRuleProtocol().equalsIgnoreCase(MatchUtils.UDP_PROTOCOL)) {
+            return EgressAclLearnServiceUtil.programEgressAclLearnRuleForUdp(flowBuilder,instructionBuilder,learnTableId,resubmitId);
+        } else if (portSecurityRule.getSecurityRuleProtocol().equalsIgnoreCase(MatchUtils.ICMP)  || portSecurityRule.getSecurityRuleProtocol().equalsIgnoreCase(MatchUtils.ICMP_PROTOCOL)) {
+            return EgressAclLearnServiceUtil.programEgressAclLearnRuleForIcmp(flowBuilder,instructionBuilder, icmpType, icmpCode,learnTableId,resubmitId);
+        }
+        return flowBuilder;
+    }
 
     private FlowBuilder addInstructionWithConntrackRecirc( FlowBuilder flowBuilder) {
         InstructionBuilder instructionBuilder = null;
@@ -875,7 +1092,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
 
             instructionBuilder = InstructionUtils
                     .createInstructionBuilder(ActionUtils.conntrackActionBuilder(conntrackAction), 1, false);
-            List<Instruction> instructionsList = Lists.newArrayList();
+            List<Instruction> instructionsList = new ArrayList<>();
             instructionsList.add(instructionBuilder.build());
             InstructionsBuilder isb = new InstructionsBuilder();
             isb.setInstruction(instructionsList);
@@ -887,7 +1104,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
     private FlowBuilder addPipelineInstruction( FlowBuilder flowBuilder ,
                                                 InstructionBuilder instructionBuilder,boolean isDrop) {
         InstructionBuilder pipeLineIndstructionBuilder = createPipleLineInstructionBuilder(isDrop);
-        List<Instruction> instructionsList = Lists.newArrayList();
+        List<Instruction> instructionsList = new ArrayList<>();
         instructionsList.add(pipeLineIndstructionBuilder.build());
         if (null != instructionBuilder) {
             instructionsList.add(instructionBuilder.build());
@@ -904,7 +1121,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA
             InstructionUtils.createDropInstructions(ib);
         }
         ib.setOrder(0);
-        List<Instruction> instructionsList = Lists.newArrayList();
+        List<Instruction> instructionsList = new ArrayList<>();
         ib.setKey(new InstructionKey(0));
         instructionsList.add(ib.build());
         return ib;