Merge "Bug 6748: ACL mechanism uses reg5 instead of reg6."
[netvirt.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / netvirt / openstack / netvirt / providers / openflow13 / services / EgressAclService.java
1 /*
2  * Copyright (c) 2014 - 2016 Red Hat, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.services;
10
11 import com.google.common.collect.Lists;
12
13 import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
14 import org.opendaylight.netvirt.openstack.netvirt.api.Constants;
15 import org.opendaylight.netvirt.openstack.netvirt.api.EgressAclProvider;
16 import org.opendaylight.netvirt.openstack.netvirt.api.SecurityGroupCacheManger;
17 import org.opendaylight.netvirt.openstack.netvirt.api.SecurityServicesManager;
18 import org.opendaylight.netvirt.openstack.netvirt.providers.ConfigInterface;
19 import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.Service;
20 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityGroup;
21 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityRule;
22 import org.opendaylight.netvirt.openstack.netvirt.translator.Neutron_IPs;
23 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronSecurityRuleCRUD;
24 import org.opendaylight.netvirt.utils.mdsal.openflow.ActionUtils;
25 import org.opendaylight.netvirt.utils.mdsal.openflow.FlowUtils;
26 import org.opendaylight.netvirt.utils.mdsal.openflow.InstructionUtils;
27 import org.opendaylight.netvirt.utils.mdsal.openflow.MatchUtils;
28 import org.opendaylight.netvirt.utils.servicehelper.ServiceHelper;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
40 import org.osgi.framework.BundleContext;
41 import org.osgi.framework.ServiceReference;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 import java.net.Inet4Address;
46 import java.net.Inet6Address;
47 import java.net.InetAddress;
48 import java.net.UnknownHostException;
49 import java.util.ArrayList;
50 import java.util.List;
51 import java.util.Map;
52
53 public class EgressAclService extends AbstractServiceInstance implements EgressAclProvider, ConfigInterface {
54
55     private static final Logger LOG = LoggerFactory.getLogger(EgressAclService.class);
56     private volatile SecurityServicesManager securityServicesManager;
57     private volatile SecurityGroupCacheManger securityGroupCacheManger;
58     private volatile INeutronSecurityRuleCRUD neutronSecurityRule;
59     private static final int DHCP_SOURCE_PORT = 67;
60     private static final int DHCP_DESTINATION_PORT = 68;
61     private static final int DHCPV6_SOURCE_PORT = 547;
62     private static final int DHCPV6_DESTINATION_PORT = 546;
63     private static final String HOST_MASK = "/32";
64     private static final String V6_HOST_MASK = "/128";
65     private static final int PORT_RANGE_MIN = 1;
66     private static final int PORT_RANGE_MAX = 65535;
67
68     public EgressAclService() {
69         super(Service.EGRESS_ACL);
70     }
71
72     public EgressAclService(Service service) {
73         super(service);
74     }
75
76     @Override
77     public void programPortSecurityGroup(Long dpid, String segmentationId, String attachedMac, long localPort,
78                                        NeutronSecurityGroup securityGroup, String portUuid, boolean write) {
79
80         LOG.trace("programPortSecurityGroup: neutronSecurityGroup: {} ", securityGroup);
81         if (securityGroup == null || getSecurityRulesforGroup(securityGroup) == null) {
82             return;
83         }
84
85         List<NeutronSecurityRule> portSecurityList = getSecurityRulesforGroup(securityGroup);
86         /* Iterate over the Port Security Rules in the Port Security Group bound to the port*/
87         for (NeutronSecurityRule portSecurityRule : portSecurityList) {
88
89             /**
90              * Neutron Port Security Acl "egress" and "IPv4"
91              * Check that the base conditions for flow based Port Security are true:
92              * Port Security Rule Direction ("egress") and Protocol ("IPv4")
93              * Neutron defines the direction "ingress" as the vSwitch to the VM as defined in:
94              * http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html
95              *
96              */
97
98             if (portSecurityRule == null
99                     || portSecurityRule.getSecurityRuleEthertype() == null
100                     || portSecurityRule.getSecurityRuleDirection() == null) {
101                 continue;
102             }
103
104             if (NeutronSecurityRule.DIRECTION_EGRESS.equals(portSecurityRule.getSecurityRuleDirection())) {
105                 LOG.debug("programPortSecurityGroup: Acl Rule matching IP and ingress is: {} ", portSecurityRule);
106                 if (null != portSecurityRule.getSecurityRemoteGroupID()) {
107                     //Remote Security group is selected
108                     List<Neutron_IPs> remoteSrcAddressList = securityServicesManager
109                             .getVmListForSecurityGroup(portUuid,portSecurityRule.getSecurityRemoteGroupID());
110                     if (null != remoteSrcAddressList) {
111                         for (Neutron_IPs vmIp :remoteSrcAddressList ) {
112
113                             programPortSecurityRule(dpid, segmentationId, attachedMac,
114                                                     localPort, portSecurityRule, vmIp, write);
115                         }
116                         if (write) {
117                             securityGroupCacheManger.addToCache(portSecurityRule.getSecurityRemoteGroupID(), portUuid);
118                         } else {
119                             securityGroupCacheManger.removeFromCache(portSecurityRule.getSecurityRemoteGroupID(),
120                                                                      portUuid);
121                         }
122                     }
123                 } else {
124                     programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
125                                             portSecurityRule, null, write);
126                 }
127                 if (write) {
128                     securityGroupCacheManger.portAdded(securityGroup.getSecurityGroupUUID(), portUuid);
129                 } else {
130                     securityGroupCacheManger.portRemoved(securityGroup.getSecurityGroupUUID(), portUuid);
131                 }
132             }
133         }
134     }
135
136     @Override
137     public void programPortSecurityRule(Long dpid, String segmentationId, String attachedMac,
138                                         long localPort, NeutronSecurityRule portSecurityRule,
139                                         Neutron_IPs vmIp, boolean write) {
140         String securityRuleEtherType = portSecurityRule.getSecurityRuleEthertype();
141         boolean isIpv6 = NeutronSecurityRule.ETHERTYPE_IPV6.equals(securityRuleEtherType);
142         if (!isIpv6 && !NeutronSecurityRule.ETHERTYPE_IPV4.equals(securityRuleEtherType)) {
143             LOG.debug("programPortSecurityRule: SecurityRuleEthertype {} does not match IPv4/v6.",
144                 securityRuleEtherType);
145             return;
146         }
147
148
149         String ipaddress = null;
150         if (null != vmIp) {
151             ipaddress = vmIp.getIpAddress();
152             try {
153                 InetAddress address = InetAddress.getByName(ipaddress);
154                 if (isIpv6 && address instanceof Inet4Address || !isIpv6 && address instanceof Inet6Address) {
155                     LOG.debug("programPortSecurityRule: Remote vmIP {} does not match with "
156                             + "SecurityRuleEthertype {}.", ipaddress, securityRuleEtherType);
157                     return;
158                 }
159             } catch (UnknownHostException e) {
160                 LOG.warn("Invalid IP address {}", ipaddress, e);
161                 return;
162             }
163         }
164         if (null == portSecurityRule.getSecurityRuleProtocol()) {
165             /* TODO Rework on the priority values */
166             egressAclIp(dpid, isIpv6, segmentationId, attachedMac,
167                 portSecurityRule, ipaddress,
168                 write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
169         } else {
170             switch (portSecurityRule.getSecurityRuleProtocol()) {
171                 case MatchUtils.TCP:
172                     LOG.debug("programPortSecurityRule: Rule matching TCP", portSecurityRule);
173                     egressAclTcp(dpid, segmentationId, attachedMac,
174                         portSecurityRule,ipaddress, write,
175                         Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
176                     break;
177                 case MatchUtils.UDP:
178                     LOG.debug("programPortSecurityRule: Rule matching UDP", portSecurityRule);
179                     egressAclUdp(dpid, segmentationId, attachedMac,
180                         portSecurityRule, ipaddress, write,
181                         Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
182                     break;
183                 case MatchUtils.ICMP:
184                 case MatchUtils.ICMPV6:
185                     LOG.debug("programPortSecurityRule: Rule matching ICMP", portSecurityRule);
186                     egressAclIcmp(dpid, segmentationId, attachedMac,
187                         portSecurityRule, ipaddress,write,
188                         Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
189                     break;
190                 default:
191                     LOG.info("programPortSecurityAcl: Protocol is not TCP/UDP/ICMP but other "
192                             + "protocol = ", portSecurityRule.getSecurityRuleProtocol());
193                     egressOtherProtocolAclHandler(dpid, segmentationId, attachedMac,
194                         portSecurityRule, ipaddress, write,
195                         Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
196                     break;
197             }
198         }
199     }
200
201     private void egressOtherProtocolAclHandler(Long dpidLong, String segmentationId, String srcMac,
202                                                NeutronSecurityRule portSecurityRule, String dstAddress,
203                                                boolean write, Integer priority) {
204         MatchBuilder matchBuilder = new MatchBuilder();
205         String flowId = "Egress_Other_" + segmentationId + "_" + srcMac + "_";
206         matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
207
208         short proto = 0;
209         try {
210             Integer protocol = new Integer(portSecurityRule.getSecurityRuleProtocol());
211             proto = protocol.shortValue();
212             flowId = flowId + proto;
213         } catch (NumberFormatException e) {
214             LOG.error("Protocol vlaue conversion failure", e);
215         }
216         matchBuilder = MatchUtils.createIpProtocolMatch(matchBuilder, proto);
217
218         if (null != dstAddress) {
219             flowId = flowId + dstAddress;
220             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
221                                                          MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
222
223         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
224             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
225             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
226                     new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
227         }
228         flowId = flowId + "_Permit";
229         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
230         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, priority, matchBuilder, getTable());
231         addInstructionWithConntrackCommit(flowBuilder, false);
232         syncFlow(flowBuilder ,nodeBuilder, write);
233     }
234
235     @Override
236     public void programFixedSecurityGroup(Long dpid, String segmentationId, String attachedMac,
237                                           long localPort, List<Neutron_IPs> srcAddressList, boolean write) {
238
239         egressAclDhcpAllowClientTrafficFromVm(dpid, write, localPort,
240                                               Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY);
241         egressAclDhcpv6AllowClientTrafficFromVm(dpid, write, localPort,
242                                                 Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY);
243         programArpRule(dpid, segmentationId, localPort, attachedMac, write);
244         if (securityServicesManager.isConntrackEnabled()) {
245             programEgressAclFixedConntrackRule(dpid, segmentationId, localPort, attachedMac, write);
246         } else {
247             // add rule to drop tcp syn packets from the vm
248             addTcpSynFlagMatchIpv4Drop(dpid, segmentationId, attachedMac, write,
249                                                          Constants.PROTO_TCP_SYN_MATCH_PRIORITY_DROP);
250             addTcpSynFlagMatchIpv6Drop(dpid, segmentationId, attachedMac, write,
251                 Constants.PROTO_TCP_SYN_MATCH_PRIORITY_DROP);
252         }
253         // add rule to drop the DHCP server traffic originating from the vm.
254         egressAclDhcpDropServerTrafficfromVm(dpid, localPort, write,
255                                              Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
256         egressAclDhcpv6DropServerTrafficfromVm(dpid, localPort, write,
257                                                Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
258     }
259
260     private void addTcpSynFlagMatchIpv4Drop(Long dpidLong, String segmentationId, String srcMac,
261                                   boolean write, Integer priority) {
262         String flowName = "Egress_TCP_Ipv4_" + segmentationId + "_" + srcMac + "_DROP";
263         MatchBuilder matchBuilder = new MatchBuilder();
264         matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
265         matchBuilder = MatchUtils.addTcpSynMatch(matchBuilder);
266         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
267         addPipelineInstruction(flowBuilder, null, true);
268         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
269         syncFlow(flowBuilder, nodeBuilder, write);
270     }
271
272     private void addTcpSynFlagMatchIpv6Drop(Long dpidLong, String segmentationId, String srcMac,
273                                         boolean write, Integer priority) {
274         String flowName = "Egress_TCP_Ipv6_" + segmentationId + "_" + srcMac + "_DROP";
275         MatchBuilder matchBuilder = new MatchBuilder();
276         matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
277         matchBuilder = MatchUtils.addTcpSynMatch(matchBuilder);
278         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
279         addPipelineInstruction(flowBuilder, null, true);
280         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
281         syncFlow(flowBuilder, nodeBuilder, write);
282     }
283
284     private void programArpRule(Long dpid, String segmentationId, long localPort, String attachedMac, boolean write) {
285         MatchBuilder matchBuilder = new MatchBuilder();
286         String flowId = "Egress_ARP_" + segmentationId + "_" + localPort + "_";
287         MatchUtils.createV4EtherMatchWithType(matchBuilder,null,null,MatchUtils.ETHERTYPE_ARP);
288         MatchUtils.addArpMacMatch(matchBuilder, attachedMac, null);
289         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, Constants.PROTO_MATCH_PRIORITY,
290                                                               matchBuilder, getTable());
291         addPipelineInstruction(flowBuilder, null, false);
292         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpid);
293         syncFlow(flowBuilder ,nodeBuilder, write);
294     }
295
296     private void programEgressAclFixedConntrackRule(Long dpid,
297                                              String segmentationId, long localPort, String attachMac, boolean write) {
298         try {
299             programConntrackUntrackRule(dpid, segmentationId, localPort,attachMac,
300                                         Constants.CT_STATE_UNTRACKED_PRIORITY, write );
301             programConntrackTrackedPlusEstRule(dpid, segmentationId, localPort,
302                                                Constants.CT_STATE_TRACKED_EXIST_PRIORITY, write );
303             programConntrackTrackedPlusRelRule(dpid, segmentationId, localPort,
304                                                Constants.CT_STATE_TRACKED_EXIST_PRIORITY, write );
305             programConntrackNewDropRule(dpid, segmentationId, localPort,
306                                         Constants.CT_STATE_NEW_PRIORITY_DROP, write );
307             programConntrackInvDropRule(dpid, segmentationId, localPort,
308                                         Constants.CT_STATE_NEW_PRIORITY_DROP, write );
309             LOG.info("programEgressAclFixedConntrackRule :  default connection tracking rule are added.");
310         } catch (Exception e) {
311             LOG.error("Failed to add default conntrack rules : " , e);
312         }
313     }
314
315     private void programConntrackUntrackRule(Long dpidLong, String segmentationId,
316                                              long localPort, String attachMac, Integer priority, boolean write) {
317         MatchBuilder matchBuilder = new MatchBuilder();
318         String flowName = "Egress_Fixed_Conntrk_Untrk_" + segmentationId + "_" + localPort + "_";
319         matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder, attachMac, null,MatchUtils.ETHERTYPE_IPV4);
320         matchBuilder = MatchUtils.addCtState(matchBuilder,MatchUtils.UNTRACKED_CT_STATE,
321                                              MatchUtils.UNTRACKED_CT_STATE_MASK);
322         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
323         addInstructionWithConntrackRecirc(flowBuilder);
324         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
325         syncFlow(flowBuilder ,nodeBuilder, write);
326     }
327
328     private void programConntrackTrackedPlusEstRule(Long dpidLong, String segmentationId,
329                                                     long localPort,Integer priority, boolean write) {
330         MatchBuilder matchBuilder = new MatchBuilder();
331         String flowName = "Egress_Fixed_Conntrk_TrkEst_" + segmentationId + "_" + localPort + "_";
332         matchBuilder = MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
333         matchBuilder = MatchUtils.addCtState(matchBuilder,MatchUtils.TRACKED_EST_CT_STATE,
334                                              MatchUtils.TRACKED_CT_STATE_MASK);
335         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
336         addPipelineInstruction(flowBuilder, null, false);
337         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
338         syncFlow(flowBuilder ,nodeBuilder, write);
339     }
340
341     private void programConntrackTrackedPlusRelRule(Long dpidLong, String segmentationId,
342                                                     long localPort,Integer priority, boolean write) {
343         MatchBuilder matchBuilder = new MatchBuilder();
344         String flowName = "Egress_Fixed_Conntrk_TrkRel_" + segmentationId + "_" + localPort + "_";
345         matchBuilder = MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
346         matchBuilder = MatchUtils.addCtState(matchBuilder,MatchUtils.TRACKED_REL_CT_STATE,
347                                              MatchUtils.TRACKED_CT_STATE_MASK);
348         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
349         addPipelineInstruction(flowBuilder, null, false);
350         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
351         syncFlow(flowBuilder ,nodeBuilder, write);
352     }
353
354     private void programConntrackNewDropRule(Long dpidLong, String segmentationId,
355                                              long localPort, Integer priority, boolean write) {
356         MatchBuilder matchBuilder = new MatchBuilder();
357
358         String flowName = "Egress_Fixed_Conntrk_NewDrop_" + segmentationId + "_" + localPort + "_";
359         matchBuilder = MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
360         matchBuilder = MatchUtils.addCtState(matchBuilder,MatchUtils.TRACKED_NEW_CT_STATE,
361                                              MatchUtils.TRACKED_NEW_CT_STATE_MASK);
362         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
363         addPipelineInstruction(flowBuilder, null, true);
364         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
365         syncFlow(flowBuilder ,nodeBuilder, write);
366     }
367
368     private void programConntrackInvDropRule(Long dpidLong, String segmentationId,
369                                              long localPort, Integer priority, boolean write) {
370         MatchBuilder matchBuilder = new MatchBuilder();
371         String flowName = "Egress_Fixed_Conntrk_InvDrop_" + segmentationId + "_" + localPort + "_";
372         matchBuilder = MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
373         matchBuilder = MatchUtils.addCtState(matchBuilder,MatchUtils.TRACKED_INV_CT_STATE,
374                                              MatchUtils.TRACKED_INV_CT_STATE_MASK);
375         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
376         addPipelineInstruction(flowBuilder, null, true);
377         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
378         syncFlow(flowBuilder ,nodeBuilder, write);
379     }
380
381     /**
382      * Allows IPv4/v6 packet egress from the src mac address.
383      * @param dpidLong the dpid
384      * @param isIpv6 whether the rule is for ipv6
385      * @param segmentationId the segementation id
386      * @param srcMac the src mac address
387      * @param write add or remove
388      * @param protoPortMatchPriority the protocol match priority.
389      */
390     private void egressAclIp(Long dpidLong, boolean isIpv6, String segmentationId, String srcMac,
391                              NeutronSecurityRule portSecurityRule, String srcAddress,
392                                boolean write, Integer protoPortMatchPriority ) {
393         MatchBuilder matchBuilder = new MatchBuilder();
394         String flowId = "Egress_IP" + segmentationId + "_" + srcMac + "_Permit_";
395         if (isIpv6) {
396             matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
397         } else {
398             matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
399         }
400         if (null != srcAddress) {
401             flowId = flowId + srcAddress;
402             if (isIpv6) {
403                 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,
404                         MatchUtils.iPv6PrefixFromIPv6Address(srcAddress),null);
405             } else {
406                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
407                         MatchUtils.iPv4PrefixFromIPv4Address(srcAddress),null);
408             }
409         } else {
410             if (isIpv6) {
411                 flowId = flowId + "Ipv6";
412             } else {
413                 flowId = flowId + "Ipv4";
414             }
415         }
416         addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
417         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority, matchBuilder, getTable());
418         addInstructionWithConntrackCommit(flowBuilder, false);
419         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
420         syncFlow(flowBuilder ,nodeBuilder, write);
421     }
422
423     /**
424      * Creates a egress match with src macaddress. If dest address is specified
425      * destination specific match will be created. Otherwise a match with a
426      * CIDR will be created.
427      * @param dpidLong the dpid
428      * @param segmentationId the segmentation id
429      * @param srcMac the source mac address.
430      * @param portSecurityRule the security rule in the SG
431      * @param dstAddress the destination IP address
432      * @param write add or delete
433      * @param protoPortMatchPriority the protocol match priroty
434      */
435     private void egressAclTcp(Long dpidLong, String segmentationId, String srcMac,
436                               NeutronSecurityRule portSecurityRule, String dstAddress,
437                               boolean write, Integer protoPortMatchPriority) {
438         boolean portRange = false;
439         MatchBuilder matchBuilder = new MatchBuilder();
440         String flowId = "Egress_TCP_" + segmentationId + "_" + srcMac + "_";
441         boolean isIpv6 = NeutronSecurityRule.ETHERTYPE_IPV6.equals(portSecurityRule.getSecurityRuleEthertype());
442         if (isIpv6) {
443             matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
444         } else {
445             matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
446         }
447
448         /* Custom TCP Match */
449         if (portSecurityRule.getSecurityRulePortMin() != null && portSecurityRule.getSecurityRulePortMax() != null) {
450             if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
451                 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
452                 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0,
453                         portSecurityRule.getSecurityRulePortMin());
454             } else if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
455                     && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
456                 /* All TCP Match */
457                 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
458                         + portSecurityRule.getSecurityRulePortMax() + "_";
459                 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0, 0);
460             } else {
461                 portRange = true;
462             }
463         }
464         if (null != dstAddress) {
465             flowId = flowId + dstAddress;
466             if (isIpv6) {
467                 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
468                         MatchUtils.iPv6PrefixFromIPv6Address(dstAddress));
469             } else {
470                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
471                         MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
472             }
473         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
474             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
475             if (isIpv6) {
476                 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
477                         new Ipv6Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
478             } else {
479                 // Fix: Bug 6473
480                 // IP match removed if CIDR created as 0.0.0.0/0 in openstack security rule
481                 if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
482                     matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
483                             new Ipv4Prefix(portSecurityRule
484                                            .getSecurityRuleRemoteIpPrefix()));
485                  }
486             }
487         }
488         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
489         if (portRange) {
490             Map<Integer, Integer> portMaskMap = MatchUtils
491                     .getLayer4MaskForRange(portSecurityRule.getSecurityRulePortMin(),
492                                            portSecurityRule.getSecurityRulePortMax());
493             for (Integer port: portMaskMap.keySet()) {
494                 String rangeflowId = flowId + port + "_" + portMaskMap.get(port) + "_";
495                 rangeflowId = rangeflowId + "_Permit";
496                 MatchUtils.addLayer4MatchWithMask(matchBuilder, MatchUtils.TCP_SHORT,
497                                                   0, port, portMaskMap.get(port));
498                 addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
499                 addTcpSynMatch(matchBuilder);
500                 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(rangeflowId, protoPortMatchPriority,
501                                                                       matchBuilder, getTable());
502                 addInstructionWithConntrackCommit(flowBuilder, false);
503                 syncFlow(flowBuilder ,nodeBuilder, write);
504             }
505         } else {
506             flowId = flowId + "_Permit";
507             addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
508             addTcpSynMatch(matchBuilder);
509             FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority,
510                                                                   matchBuilder, getTable());
511             addInstructionWithConntrackCommit(flowBuilder, false);
512             syncFlow(flowBuilder ,nodeBuilder, write);
513         }
514     }
515
516     private void addTcpSynMatch(MatchBuilder matchBuilder) {
517         if (!securityServicesManager.isConntrackEnabled()) {
518             MatchUtils.createTcpProtoSynMatch(matchBuilder);
519         }
520     }
521
522     private void egressAclIcmp(Long dpidLong, String segmentationId, String srcMac,
523             NeutronSecurityRule portSecurityRule, String dstAddress,
524             boolean write, Integer protoPortMatchPriority) {
525
526         boolean isIpv6 = NeutronSecurityRule.ETHERTYPE_IPV6.equals(portSecurityRule.getSecurityRuleEthertype());
527         if (isIpv6) {
528             egressAclIcmpV6(dpidLong, segmentationId, srcMac, portSecurityRule, dstAddress, write,
529                             protoPortMatchPriority);
530         } else {
531             egressAclIcmpV4(dpidLong, segmentationId, srcMac, portSecurityRule, dstAddress, write,
532                             protoPortMatchPriority);
533         }
534     }
535
536     /**
537      * Creates a icmp egress match with src macaddress. If dest address is specified
538      * destination specific match will be created. Otherwise a match with a
539      * CIDR will be created.
540      * @param dpidLong the dpid
541      * @param segmentationId the segmentation id
542      * @param srcMac the source mac address.
543      * @param portSecurityRule the security rule in the SG
544      * @param dstAddress the source IP address
545      * @param write add or delete
546      * @param protoPortMatchPriority the protocol match priority
547      */
548     private void egressAclIcmpV4(Long dpidLong, String segmentationId, String srcMac,
549                                  NeutronSecurityRule portSecurityRule, String dstAddress,
550                                  boolean write, Integer protoPortMatchPriority) {
551
552         MatchBuilder matchBuilder = new MatchBuilder();
553         String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_";
554         matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
555         /*Custom ICMP Match */
556         if (portSecurityRule.getSecurityRulePortMin() != null
557                 && portSecurityRule.getSecurityRulePortMax() != null) {
558             flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
559                     + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
560             matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,
561                     portSecurityRule.getSecurityRulePortMin().shortValue(),
562                     portSecurityRule.getSecurityRulePortMax().shortValue());
563         } else {
564             /* All ICMP Match */ // We are getting from neutron NULL for both min and max
565             flowId = flowId + "all" + "_" ;
566             matchBuilder = MatchUtils.createICMPv4Match(matchBuilder, MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
567         }
568         if (null != dstAddress) {
569             flowId = flowId + dstAddress;
570             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
571                     MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
572         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
573             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
574             if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
575                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
576                     new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
577             }
578         }
579         flowId = flowId + "_Permit";
580         addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
581         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
582         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority, matchBuilder, getTable());
583         addInstructionWithConntrackCommit(flowBuilder, false);
584         syncFlow(flowBuilder ,nodeBuilder, write);
585     }
586
587     /**
588      * Creates a icmpv6 egress match with src macaddress. If dest address is specified
589      * destination specific match will be created. Otherwise a match with a
590      * CIDR will be created.
591      * @param dpidLong the dpid
592      * @param segmentationId the segmentation id
593      * @param srcMac the source mac address.
594      * @param portSecurityRule the security rule in the SG
595      * @param dstAddress the source IP address
596      * @param write add or delete
597      * @param protoPortMatchPriority the protocol match priority
598      */
599     private void egressAclIcmpV6(Long dpidLong, String segmentationId, String srcMac,
600                                  NeutronSecurityRule portSecurityRule, String dstAddress,
601                                  boolean write, Integer protoPortMatchPriority) {
602
603         MatchBuilder matchBuilder = new MatchBuilder();
604         String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_";
605         matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
606
607         /*Custom ICMP Match */
608         if (portSecurityRule.getSecurityRulePortMin() != null
609                 && portSecurityRule.getSecurityRulePortMax() != null) {
610             flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
611                     + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
612             matchBuilder = MatchUtils.createICMPv6Match(matchBuilder,
613                     portSecurityRule.getSecurityRulePortMin().shortValue(),
614                     portSecurityRule.getSecurityRulePortMax().shortValue());
615         } else {
616             /* All ICMP Match */ // We are getting from neutron NULL for both min and max
617             flowId = flowId + "all" + "_" ;
618             matchBuilder = MatchUtils.createICMPv6Match(matchBuilder, MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
619         }
620         if (null != dstAddress) {
621             flowId = flowId + dstAddress;
622             matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
623                     MatchUtils.iPv6PrefixFromIPv6Address(dstAddress));
624         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
625             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
626             matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
627                     new Ipv6Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
628         }
629         flowId = flowId + "_Permit";
630         addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
631         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
632         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority, matchBuilder, getTable());
633         addInstructionWithConntrackCommit(flowBuilder, false);
634         syncFlow(flowBuilder ,nodeBuilder, write);
635     }
636
637     /**
638      * Creates a egress match with src macaddress. If dest address is specified
639      * destination specific match will be created. Otherwise a match with a
640      * CIDR will be created.
641      * @param dpidLong the dpid
642      * @param segmentationId the segmentation id
643      * @param srcMac the source mac address.
644      * @param portSecurityRule the security rule in the SG
645      * @param dstAddress the source IP address
646      * @param write add or delete
647      * @param protoPortMatchPriority the protocol match priroty
648      */
649     private void egressAclUdp(Long dpidLong, String segmentationId, String srcMac,
650                               NeutronSecurityRule portSecurityRule, String dstAddress,
651                               boolean write, Integer protoPortMatchPriority) {
652         boolean portRange = false;
653         MatchBuilder matchBuilder = new MatchBuilder();
654         String flowId = "Egress_UDP_" + segmentationId + "_" + srcMac + "_";
655         boolean isIpv6 = NeutronSecurityRule.ETHERTYPE_IPV6.equals(portSecurityRule.getSecurityRuleEthertype());
656         if (isIpv6) {
657             matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
658         } else {
659             matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
660         }
661
662         /* Custom UDP Match */
663         if (portSecurityRule.getSecurityRulePortMin() != null && portSecurityRule.getSecurityRulePortMax() != null) {
664             if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
665                 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
666                 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0,
667                         portSecurityRule.getSecurityRulePortMin());
668             } else if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
669                     && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
670                 /* All UDP Match */
671                 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
672                         + portSecurityRule.getSecurityRulePortMax() + "_";
673                 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0, 0);
674             } else {
675                 portRange = true;
676             }
677         }
678         if (null != dstAddress) {
679             flowId = flowId + dstAddress;
680             if (isIpv6) {
681                 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
682                         MatchUtils.iPv6PrefixFromIPv6Address(dstAddress));
683             } else {
684                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
685                         MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
686             }
687         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
688             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
689             if (isIpv6) {
690                 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder, null,
691                         new Ipv6Prefix(portSecurityRule
692                                        .getSecurityRuleRemoteIpPrefix()));
693             } else {
694                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
695                         new Ipv4Prefix(portSecurityRule
696                                        .getSecurityRuleRemoteIpPrefix()));
697             }
698         }
699         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
700         if (portRange) {
701             Map<Integer, Integer> portMaskMap = MatchUtils
702                     .getLayer4MaskForRange(portSecurityRule.getSecurityRulePortMin(),
703                                            portSecurityRule.getSecurityRulePortMax());
704             for (Integer port: portMaskMap.keySet()) {
705                 String rangeflowId = flowId + port + "_" + portMaskMap.get(port) + "_";
706                 rangeflowId = rangeflowId + "_Permit";
707                 MatchUtils.addLayer4MatchWithMask(matchBuilder, MatchUtils.UDP_SHORT,
708                                                   0, port, portMaskMap.get(port));
709                 addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
710                 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(rangeflowId, protoPortMatchPriority,
711                                                                       matchBuilder, getTable());
712                 addInstructionWithConntrackCommit(flowBuilder, false);
713                 syncFlow(flowBuilder ,nodeBuilder, write);
714             }
715         } else {
716             flowId = flowId + "_Permit";
717             addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
718             FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority,
719                                                                   matchBuilder, getTable());
720             addInstructionWithConntrackCommit(flowBuilder, false);
721             syncFlow(flowBuilder ,nodeBuilder, write);
722         }
723     }
724
725     /**
726      * Adds flow to allow any DHCP client traffic.
727      *
728      * @param dpidLong the dpid
729      * @param write whether to write or delete the flow
730      * @param localPort the local port.
731      * @param priority the priority
732      */
733     private void egressAclDhcpAllowClientTrafficFromVm(Long dpidLong,
734                                                        boolean write, long localPort, Integer priority) {
735         String flowName = "Egress_DHCP_Client"  + "_Permit_";
736         MatchBuilder matchBuilder = new MatchBuilder();
737         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
738         MatchUtils.createDhcpMatch(matchBuilder, DHCP_DESTINATION_PORT, DHCP_SOURCE_PORT);
739         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
740         addPipelineInstruction(flowBuilder, null, false);
741         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
742         syncFlow(flowBuilder ,nodeBuilder, write);
743     }
744
745     /**
746      * Adds flow to allow any DHCP IPv6 client traffic.
747      *
748      * @param dpidLong the dpid
749      * @param write whether to write or delete the flow
750      * @param localPort the local port
751      * @param priority the priority
752      */
753     private void egressAclDhcpv6AllowClientTrafficFromVm(Long dpidLong,
754                                                          boolean write, long localPort, Integer priority) {
755         String flowName = "Egress_DHCPv6_Client"  + "_Permit_";
756         MatchBuilder matchBuilder = new MatchBuilder();
757         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
758         MatchUtils.createDhcpv6Match(matchBuilder, DHCPV6_DESTINATION_PORT, DHCPV6_SOURCE_PORT);
759         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
760         addPipelineInstruction(flowBuilder, null, false);
761         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
762         syncFlow(flowBuilder ,nodeBuilder, write);
763     }
764
765     /**
766      * Adds rule to prevent DHCP spoofing by the vm attached to the port.
767      *
768      * @param dpidLong the dpid
769      * @param localPort the local port
770      * @param write is write or delete
771      * @param priority  the priority
772      */
773     private void egressAclDhcpDropServerTrafficfromVm(Long dpidLong, long localPort,
774                                                       boolean write, Integer priority) {
775         String flowName = "Egress_DHCP_Server_" + localPort + "_DROP";
776         MatchBuilder matchBuilder = new MatchBuilder();
777         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
778         MatchUtils.createDhcpMatch(matchBuilder, DHCP_SOURCE_PORT, DHCP_DESTINATION_PORT);
779         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
780         addPipelineInstruction(flowBuilder, null, true);
781         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
782         syncFlow(flowBuilder ,nodeBuilder, write);
783     }
784
785     /**
786      * Adds rule to prevent DHCPv6 spoofing by the vm attached to the port.
787      *
788      * @param dpidLong the dpid
789      * @param localPort the local port
790      * @param write is write or delete
791      * @param priority  the priority
792      */
793     private void egressAclDhcpv6DropServerTrafficfromVm(Long dpidLong, long localPort,
794                                                         boolean write, Integer priority) {
795
796         String flowName = "Egress_DHCPv6_Server_" + "_" + localPort + "_DROP";
797         MatchBuilder matchBuilder = new MatchBuilder();
798         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
799         MatchUtils.createDhcpv6Match(matchBuilder, DHCPV6_SOURCE_PORT, DHCPV6_DESTINATION_PORT);
800         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
801         addPipelineInstruction(flowBuilder, null, true);
802         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
803         syncFlow(flowBuilder ,nodeBuilder, write);
804     }
805
806     /**
807      * Adds rule to check legitimate ip/mac pair for each packet from the vm.
808      *
809      * @param dpidLong the dpid
810      * @param localPort the local port
811      * @param srcIp the vm ip address
812      * @param attachedMac the vm mac address
813      * @param priority  the priority
814      * @param write is write or delete
815      */
816     private void egressAclAllowTrafficFromVmIpMacPair(Long dpidLong, long localPort,
817                                                       String attachedMac, String srcIp,
818                                                       Integer priority, boolean write) {
819         MatchBuilder matchBuilder = new MatchBuilder();
820         MatchUtils.createSrcL3Ipv4MatchWithMac(matchBuilder, new Ipv4Prefix(srcIp),new MacAddress(attachedMac));
821         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
822         LOG.debug("egressAclAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", matchBuilder);
823         String flowName = "Egress_Allow_VM_IP_MAC" + "_" + localPort + attachedMac + "_Permit_";
824         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
825         addPipelineInstruction(flowBuilder, null, false);
826         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
827         syncFlow(flowBuilder ,nodeBuilder, write);
828     }
829
830     /**
831      * Adds rule to check legitimate ip/mac pair for each packet from the vm.
832      *
833      * @param dpidLong the dpid
834      * @param localPort the local port
835      * @param srcIp the vm ip address
836      * @param attachedMac the vm mac address
837      * @param priority  the priority
838      * @param write is write or delete
839      */
840     private void egressAclAllowTrafficFromVmIpV6MacPair(Long dpidLong, long localPort,
841                                                         String attachedMac, String srcIp,
842                                                         Integer priority, boolean write) {
843         MatchBuilder matchBuilder = new MatchBuilder();
844         MatchUtils.createSrcL3Ipv6MatchWithMac(matchBuilder, new Ipv6Prefix(srcIp),new MacAddress(attachedMac));
845         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
846         LOG.debug("egressAclAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", matchBuilder);
847         String flowName = "Egress_Allow_VM_IPv6_MAC" + "_" + localPort + attachedMac + "_Permit_";
848         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
849         addPipelineInstruction(flowBuilder, null, false);
850         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
851         syncFlow(flowBuilder ,nodeBuilder, write);
852     }
853
854     private void addConntrackMatch(MatchBuilder matchBuilder, int state, int mask) {
855         if (securityServicesManager.isConntrackEnabled()) {
856             MatchUtils.addCtState(matchBuilder, state, mask );
857         }
858
859     }
860
861     private FlowBuilder addInstructionWithConntrackCommit( FlowBuilder flowBuilder , boolean isDrop) {
862         InstructionBuilder instructionBuilder = null;
863         if (securityServicesManager.isConntrackEnabled()) {
864             Action conntrackAction = ActionUtils.nxConntrackAction(1, 0L, 0, (short)0xff);
865             instructionBuilder = InstructionUtils
866                     .createInstructionBuilder(ActionUtils.conntrackActionBuilder(conntrackAction), 1, false);
867         }
868         return addPipelineInstruction(flowBuilder,instructionBuilder, isDrop);
869     }
870
871     private FlowBuilder addInstructionWithConntrackRecirc( FlowBuilder flowBuilder) {
872         InstructionBuilder instructionBuilder = null;
873         if (securityServicesManager.isConntrackEnabled()) {
874             Action conntrackAction = ActionUtils.nxConntrackAction(0, 0L, 0, (short)0x0);
875
876             instructionBuilder = InstructionUtils
877                     .createInstructionBuilder(ActionUtils.conntrackActionBuilder(conntrackAction), 1, false);
878             List<Instruction> instructionsList = Lists.newArrayList();
879             instructionsList.add(instructionBuilder.build());
880             InstructionsBuilder isb = new InstructionsBuilder();
881             isb.setInstruction(instructionsList);
882             flowBuilder.setInstructions(isb.build());
883         }
884         return flowBuilder;
885     }
886
887     private FlowBuilder addPipelineInstruction( FlowBuilder flowBuilder ,
888                                                 InstructionBuilder instructionBuilder,boolean isDrop) {
889         InstructionBuilder pipeLineIndstructionBuilder = createPipleLineInstructionBuilder(isDrop);
890         List<Instruction> instructionsList = Lists.newArrayList();
891         instructionsList.add(pipeLineIndstructionBuilder.build());
892         if (null != instructionBuilder) {
893             instructionsList.add(instructionBuilder.build());
894         }
895         InstructionsBuilder isb = new InstructionsBuilder();
896         isb.setInstruction(instructionsList);
897         flowBuilder.setInstructions(isb.build());
898         return flowBuilder;
899     }
900
901     private InstructionBuilder createPipleLineInstructionBuilder(boolean drop) {
902         InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
903         if (drop) {
904             InstructionUtils.createDropInstructions(ib);
905         }
906         ib.setOrder(0);
907         List<Instruction> instructionsList = Lists.newArrayList();
908         ib.setKey(new InstructionKey(0));
909         instructionsList.add(ib.build());
910         return ib;
911     }
912     /**
913      * Add or remove flow to the node.
914      * @param flowBuilder the flow builder
915      * @param nodeBuilder the node builder
916      * @param write whether it is a write
917      */
918     private void syncFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder,
919                           boolean write) {
920         if (write) {
921             writeFlow(flowBuilder, nodeBuilder);
922         } else {
923             removeFlow(flowBuilder, nodeBuilder);
924         }
925     }
926
927     private List<NeutronSecurityRule> getSecurityRulesforGroup(NeutronSecurityGroup securityGroup) {
928         List<NeutronSecurityRule> securityRules = new ArrayList<>();
929         List<NeutronSecurityRule> rules = neutronSecurityRule.getAllNeutronSecurityRules();
930         for (NeutronSecurityRule securityRule : rules) {
931             if (securityGroup.getID().equals(securityRule.getSecurityRuleGroupID())) {
932                 securityRules.add(securityRule);
933             }
934         }
935         return securityRules;
936     }
937
938     @Override
939     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
940         super.setDependencies(bundleContext.getServiceReference(EgressAclProvider.class.getName()), this);
941         securityServicesManager =
942                 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
943         securityGroupCacheManger =
944                 (SecurityGroupCacheManger) ServiceHelper.getGlobalInstance(SecurityGroupCacheManger.class, this);
945         neutronSecurityRule = (INeutronSecurityRuleCRUD) ServiceHelper.getGlobalInstance(INeutronSecurityRuleCRUD.class, this);
946     }
947
948     @Override
949     public void setDependencies(Object impl) {}
950 }