Merge "aclservice Java @Inject etc. instead of XML for "inner" wiring"
[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         if (null == portSecurityRule.getSecurityRuleProtocol()) {
149             /* TODO Rework on the priority values */
150             egressAclIp(dpid, isIpv6, segmentationId, attachedMac,
151                           write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
152         } else {
153             String ipaddress = null;
154             if (null != vmIp) {
155                 ipaddress = vmIp.getIpAddress();
156                 try {
157                     InetAddress address = InetAddress.getByName(ipaddress);
158                     if (isIpv6 && address instanceof Inet4Address || !isIpv6 && address instanceof Inet6Address) {
159                         LOG.debug("programPortSecurityRule: Remote vmIP {} does not match with "
160                                 + "SecurityRuleEthertype {}.", ipaddress, securityRuleEtherType);
161                         return;
162                     }
163                 } catch (UnknownHostException e) {
164                     LOG.warn("Invalid IP address {}", ipaddress, e);
165                     return;
166                 }
167             }
168
169             switch (portSecurityRule.getSecurityRuleProtocol()) {
170                 case MatchUtils.TCP:
171                     LOG.debug("programPortSecurityRule: Rule matching TCP", portSecurityRule);
172                     egressAclTcp(dpid, segmentationId, attachedMac,
173                              portSecurityRule,ipaddress, write,
174                              Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
175                     break;
176                 case MatchUtils.UDP:
177                     LOG.debug("programPortSecurityRule: Rule matching UDP", portSecurityRule);
178                     egressAclUdp(dpid, segmentationId, attachedMac,
179                              portSecurityRule, ipaddress, write,
180                              Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
181                     break;
182                 case MatchUtils.ICMP:
183                 case MatchUtils.ICMPV6:
184                     LOG.debug("programPortSecurityRule: Rule matching ICMP", portSecurityRule);
185                     egressAclIcmp(dpid, segmentationId, attachedMac,
186                               portSecurityRule, ipaddress,write,
187                               Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
188                     break;
189                 default:
190                     LOG.info("programPortSecurityAcl: Protocol is not TCP/UDP/ICMP but other "
191                             + "protocol = ", portSecurityRule.getSecurityRuleProtocol());
192                     egressOtherProtocolAclHandler(dpid, segmentationId, attachedMac,
193                                               portSecurityRule, ipaddress, write,
194                                               Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
195                     break;
196             }
197         }
198     }
199
200     private void egressOtherProtocolAclHandler(Long dpidLong, String segmentationId, String srcMac,
201                                                NeutronSecurityRule portSecurityRule, String dstAddress,
202                                                boolean write, Integer priority) {
203         MatchBuilder matchBuilder = new MatchBuilder();
204         String flowId = "Egress_Other_" + segmentationId + "_" + srcMac + "_";
205         matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
206
207         short proto = 0;
208         try {
209             Integer protocol = new Integer(portSecurityRule.getSecurityRuleProtocol());
210             proto = protocol.shortValue();
211             flowId = flowId + proto;
212         } catch (NumberFormatException e) {
213             LOG.error("Protocol vlaue conversion failure", e);
214         }
215         matchBuilder = MatchUtils.createIpProtocolMatch(matchBuilder, proto);
216
217         if (null != dstAddress) {
218             flowId = flowId + dstAddress;
219             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
220                                                          MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
221
222         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
223             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
224             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
225                     new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
226         }
227         flowId = flowId + "_Permit";
228         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
229         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, priority, matchBuilder, getTable());
230         addInstructionWithConntrackCommit(flowBuilder, false);
231         syncFlow(flowBuilder ,nodeBuilder, write);
232     }
233
234     @Override
235     public void programFixedSecurityGroup(Long dpid, String segmentationId, String attachedMac,
236                                           long localPort, List<Neutron_IPs> srcAddressList, boolean write) {
237
238         egressAclDhcpAllowClientTrafficFromVm(dpid, write, localPort,
239                                               Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY);
240         egressAclDhcpv6AllowClientTrafficFromVm(dpid, write, localPort,
241                                                 Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY);
242         programArpRule(dpid, segmentationId, localPort, attachedMac, write);
243         if (securityServicesManager.isConntrackEnabled()) {
244             programEgressAclFixedConntrackRule(dpid, segmentationId, localPort, attachedMac, write);
245         } else {
246             // add rule to drop tcp syn packets from the vm
247             addTcpSynFlagMatchIpv4Drop(dpid, segmentationId, attachedMac, write,
248                                                          Constants.PROTO_TCP_SYN_MATCH_PRIORITY_DROP);
249             addTcpSynFlagMatchIpv6Drop(dpid, segmentationId, attachedMac, write,
250                 Constants.PROTO_TCP_SYN_MATCH_PRIORITY_DROP);
251         }
252         // add rule to drop the DHCP server traffic originating from the vm.
253         egressAclDhcpDropServerTrafficfromVm(dpid, localPort, write,
254                                              Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
255         egressAclDhcpv6DropServerTrafficfromVm(dpid, localPort, write,
256                                                Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
257     }
258
259     private void addTcpSynFlagMatchIpv4Drop(Long dpidLong, String segmentationId, String srcMac,
260                                   boolean write, Integer priority) {
261         String flowName = "Egress_TCP_Ipv4" + segmentationId + "_" + srcMac + "_DROP_";
262         MatchBuilder matchBuilder = new MatchBuilder();
263         flowName = flowName + "_";
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         flowName = flowName + "_";
277         matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
278         matchBuilder = MatchUtils.addTcpSynMatch(matchBuilder);
279         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
280         addPipelineInstruction(flowBuilder, null, true);
281         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
282         syncFlow(flowBuilder, nodeBuilder, write);
283     }
284
285     private void programArpRule(Long dpid, String segmentationId, long localPort, String attachedMac, boolean write) {
286         MatchBuilder matchBuilder = new MatchBuilder();
287         String flowId = "Egress_ARP_" + segmentationId + "_" + localPort + "_";
288         MatchUtils.createV4EtherMatchWithType(matchBuilder,null,null,MatchUtils.ETHERTYPE_ARP);
289         MatchUtils.addArpMacMatch(matchBuilder, attachedMac, null);
290         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, Constants.PROTO_MATCH_PRIORITY,
291                                                               matchBuilder, getTable());
292         addPipelineInstruction(flowBuilder, null, false);
293         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpid);
294         syncFlow(flowBuilder ,nodeBuilder, write);
295     }
296
297     private void programEgressAclFixedConntrackRule(Long dpid,
298                                              String segmentationId, long localPort, String attachMac, boolean write) {
299         try {
300             programConntrackUntrackRule(dpid, segmentationId, localPort,attachMac,
301                                         Constants.CT_STATE_UNTRACKED_PRIORITY, write );
302             programConntrackTrackedPlusEstRule(dpid, segmentationId, localPort,
303                                                Constants.CT_STATE_TRACKED_EXIST_PRIORITY, write );
304             programConntrackTrackedPlusRelRule(dpid, segmentationId, localPort,
305                                                Constants.CT_STATE_TRACKED_EXIST_PRIORITY, write );
306             programConntrackNewDropRule(dpid, segmentationId, localPort,
307                                         Constants.CT_STATE_NEW_PRIORITY_DROP, write );
308             programConntrackInvDropRule(dpid, segmentationId, localPort,
309                                         Constants.CT_STATE_NEW_PRIORITY_DROP, write );
310             LOG.info("programEgressAclFixedConntrackRule :  default connection tracking rule are added.");
311         } catch (Exception e) {
312             LOG.error("Failed to add default conntrack rules : " , e);
313         }
314     }
315
316     private void programConntrackUntrackRule(Long dpidLong, String segmentationId,
317                                              long localPort, String attachMac, Integer priority, boolean write) {
318         MatchBuilder matchBuilder = new MatchBuilder();
319         String flowName = "Egress_Fixed_Conntrk_Untrk_" + segmentationId + "_" + localPort + "_";
320         matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder, attachMac, null,MatchUtils.ETHERTYPE_IPV4);
321         matchBuilder = MatchUtils.addCtState(matchBuilder,MatchUtils.UNTRACKED_CT_STATE,
322                                              MatchUtils.UNTRACKED_CT_STATE_MASK);
323         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
324         addInstructionWithConntrackRecirc(flowBuilder);
325         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
326         syncFlow(flowBuilder ,nodeBuilder, write);
327     }
328
329     private void programConntrackTrackedPlusEstRule(Long dpidLong, String segmentationId,
330                                                     long localPort,Integer priority, boolean write) {
331         MatchBuilder matchBuilder = new MatchBuilder();
332         String flowName = "Egress_Fixed_Conntrk_TrkEst_" + segmentationId + "_" + localPort + "_";
333         matchBuilder = MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
334         matchBuilder = MatchUtils.addCtState(matchBuilder,MatchUtils.TRACKED_EST_CT_STATE,
335                                              MatchUtils.TRACKED_CT_STATE_MASK);
336         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
337         addPipelineInstruction(flowBuilder, null, false);
338         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
339         syncFlow(flowBuilder ,nodeBuilder, write);
340     }
341
342     private void programConntrackTrackedPlusRelRule(Long dpidLong, String segmentationId,
343                                                     long localPort,Integer priority, boolean write) {
344         MatchBuilder matchBuilder = new MatchBuilder();
345         String flowName = "Egress_Fixed_Conntrk_TrkRel_" + segmentationId + "_" + localPort + "_";
346         matchBuilder = MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
347         matchBuilder = MatchUtils.addCtState(matchBuilder,MatchUtils.TRACKED_REL_CT_STATE,
348                                              MatchUtils.TRACKED_CT_STATE_MASK);
349         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
350         addPipelineInstruction(flowBuilder, null, false);
351         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
352         syncFlow(flowBuilder ,nodeBuilder, write);
353     }
354
355     private void programConntrackNewDropRule(Long dpidLong, String segmentationId,
356                                              long localPort, Integer priority, boolean write) {
357         MatchBuilder matchBuilder = new MatchBuilder();
358
359         String flowName = "Egress_Fixed_Conntrk_NewDrop_" + segmentationId + "_" + localPort + "_";
360         matchBuilder = MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
361         matchBuilder = MatchUtils.addCtState(matchBuilder,MatchUtils.TRACKED_NEW_CT_STATE,
362                                              MatchUtils.TRACKED_NEW_CT_STATE_MASK);
363         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
364         addPipelineInstruction(flowBuilder, null, true);
365         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
366         syncFlow(flowBuilder ,nodeBuilder, write);
367     }
368
369     private void programConntrackInvDropRule(Long dpidLong, String segmentationId,
370                                              long localPort, Integer priority, boolean write) {
371         MatchBuilder matchBuilder = new MatchBuilder();
372         String flowName = "Egress_Fixed_Conntrk_InvDrop_" + segmentationId + "_" + localPort + "_";
373         matchBuilder = MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
374         matchBuilder = MatchUtils.addCtState(matchBuilder,MatchUtils.TRACKED_INV_CT_STATE,
375                                              MatchUtils.TRACKED_INV_CT_STATE_MASK);
376         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
377         addPipelineInstruction(flowBuilder, null, true);
378         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
379         syncFlow(flowBuilder ,nodeBuilder, write);
380     }
381
382     /**
383      * Allows IPv4/v6 packet egress from the src mac address.
384      * @param dpidLong the dpid
385      * @param isIpv6 whether the rule is for ipv6
386      * @param segmentationId the segementation id
387      * @param srcMac the src mac address
388      * @param write add or remove
389      * @param protoPortMatchPriority the protocol match priority.
390      */
391     private void egressAclIp(Long dpidLong, boolean isIpv6, String segmentationId, String srcMac,
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         addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
401         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority, matchBuilder, getTable());
402         addInstructionWithConntrackCommit(flowBuilder, false);
403         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
404         syncFlow(flowBuilder ,nodeBuilder, write);
405     }
406
407     /**
408      * Creates a egress match with src macaddress. If dest address is specified
409      * destination specific match will be created. Otherwise a match with a
410      * CIDR will be created.
411      * @param dpidLong the dpid
412      * @param segmentationId the segmentation id
413      * @param srcMac the source mac address.
414      * @param portSecurityRule the security rule in the SG
415      * @param dstAddress the destination IP address
416      * @param write add or delete
417      * @param protoPortMatchPriority the protocol match priroty
418      */
419     private void egressAclTcp(Long dpidLong, String segmentationId, String srcMac,
420                               NeutronSecurityRule portSecurityRule, String dstAddress,
421                               boolean write, Integer protoPortMatchPriority) {
422         boolean portRange = false;
423         MatchBuilder matchBuilder = new MatchBuilder();
424         String flowId = "Egress_TCP_" + segmentationId + "_" + srcMac + "_";
425         boolean isIpv6 = NeutronSecurityRule.ETHERTYPE_IPV6.equals(portSecurityRule.getSecurityRuleEthertype());
426         if (isIpv6) {
427             matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
428         } else {
429             matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
430         }
431
432         /* Custom TCP Match */
433         if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
434             flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
435             matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0,
436                                                      portSecurityRule.getSecurityRulePortMin());
437         } else {
438             /* All TCP Match */
439             if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
440                     && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
441                 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
442                             + portSecurityRule.getSecurityRulePortMax() + "_";
443                 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0, 0);
444             } else {
445                 portRange = true;
446             }
447         }
448         if (null != dstAddress) {
449             flowId = flowId + dstAddress;
450             if (isIpv6) {
451                 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
452                         MatchUtils.iPv6PrefixFromIPv6Address(dstAddress));
453             } else {
454                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
455                         MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
456             }
457         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
458             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
459             if (isIpv6) {
460                 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
461                         new Ipv6Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
462             } else {
463                 // Fix: Bug 6473
464                 // IP match removed if CIDR created as 0.0.0.0/0 in openstack security rule
465                 if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
466                     matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
467                             new Ipv4Prefix(portSecurityRule
468                                            .getSecurityRuleRemoteIpPrefix()));
469                  }
470             }
471         }
472         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
473         if (portRange) {
474             Map<Integer, Integer> portMaskMap = MatchUtils
475                     .getLayer4MaskForRange(portSecurityRule.getSecurityRulePortMin(),
476                                            portSecurityRule.getSecurityRulePortMax());
477             for (Integer port: portMaskMap.keySet()) {
478                 String rangeflowId = flowId + port + "_" + portMaskMap.get(port) + "_";
479                 rangeflowId = rangeflowId + "_Permit";
480                 MatchUtils.addLayer4MatchWithMask(matchBuilder, MatchUtils.TCP_SHORT,
481                                                   0, port, portMaskMap.get(port));
482                 addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
483                 addTcpSynMatch(matchBuilder);
484                 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(rangeflowId, protoPortMatchPriority,
485                                                                       matchBuilder, getTable());
486                 addInstructionWithConntrackCommit(flowBuilder, false);
487                 syncFlow(flowBuilder ,nodeBuilder, write);
488             }
489         } else {
490             flowId = flowId + "_Permit";
491             addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
492             addTcpSynMatch(matchBuilder);
493             FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority,
494                                                                   matchBuilder, getTable());
495             addInstructionWithConntrackCommit(flowBuilder, false);
496             syncFlow(flowBuilder ,nodeBuilder, write);
497         }
498     }
499
500     private void addTcpSynMatch(MatchBuilder matchBuilder) {
501         if (!securityServicesManager.isConntrackEnabled()) {
502             MatchUtils.createTcpProtoSynMatch(matchBuilder);
503         }
504     }
505
506     private void egressAclIcmp(Long dpidLong, String segmentationId, String srcMac,
507             NeutronSecurityRule portSecurityRule, String dstAddress,
508             boolean write, Integer protoPortMatchPriority) {
509
510         boolean isIpv6 = NeutronSecurityRule.ETHERTYPE_IPV6.equals(portSecurityRule.getSecurityRuleEthertype());
511         if (isIpv6) {
512             egressAclIcmpV6(dpidLong, segmentationId, srcMac, portSecurityRule, dstAddress, write,
513                             protoPortMatchPriority);
514         } else {
515             egressAclIcmpV4(dpidLong, segmentationId, srcMac, portSecurityRule, dstAddress, write,
516                             protoPortMatchPriority);
517         }
518     }
519
520     /**
521      * Creates a icmp egress match with src macaddress. If dest address is specified
522      * destination specific match will be created. Otherwise a match with a
523      * CIDR will be created.
524      * @param dpidLong the dpid
525      * @param segmentationId the segmentation id
526      * @param srcMac the source mac address.
527      * @param portSecurityRule the security rule in the SG
528      * @param dstAddress the source IP address
529      * @param write add or delete
530      * @param protoPortMatchPriority the protocol match priority
531      */
532     private void egressAclIcmpV4(Long dpidLong, String segmentationId, String srcMac,
533                                  NeutronSecurityRule portSecurityRule, String dstAddress,
534                                  boolean write, Integer protoPortMatchPriority) {
535
536         MatchBuilder matchBuilder = new MatchBuilder();
537         String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_";
538         matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
539         /*Custom ICMP Match */
540         if (portSecurityRule.getSecurityRulePortMin() != null
541                 && portSecurityRule.getSecurityRulePortMax() != null) {
542             flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
543                     + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
544             matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,
545                     portSecurityRule.getSecurityRulePortMin().shortValue(),
546                     portSecurityRule.getSecurityRulePortMax().shortValue());
547         } else {
548             /* All ICMP Match */ // We are getting from neutron NULL for both min and max
549             flowId = flowId + "all" + "_" ;
550             matchBuilder = MatchUtils.createICMPv4Match(matchBuilder, MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
551         }
552         if (null != dstAddress) {
553             flowId = flowId + dstAddress;
554             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
555                     MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
556         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
557             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
558             if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
559                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
560                     new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
561             }
562         }
563         flowId = flowId + "_Permit";
564         addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
565         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
566         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority, matchBuilder, getTable());
567         addInstructionWithConntrackCommit(flowBuilder, false);
568         syncFlow(flowBuilder ,nodeBuilder, write);
569     }
570
571     /**
572      * Creates a icmpv6 egress match with src macaddress. If dest address is specified
573      * destination specific match will be created. Otherwise a match with a
574      * CIDR will be created.
575      * @param dpidLong the dpid
576      * @param segmentationId the segmentation id
577      * @param srcMac the source mac address.
578      * @param portSecurityRule the security rule in the SG
579      * @param dstAddress the source IP address
580      * @param write add or delete
581      * @param protoPortMatchPriority the protocol match priority
582      */
583     private void egressAclIcmpV6(Long dpidLong, String segmentationId, String srcMac,
584                                  NeutronSecurityRule portSecurityRule, String dstAddress,
585                                  boolean write, Integer protoPortMatchPriority) {
586
587         MatchBuilder matchBuilder = new MatchBuilder();
588         String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_";
589         matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
590
591         /*Custom ICMP Match */
592         if (portSecurityRule.getSecurityRulePortMin() != null
593                 && portSecurityRule.getSecurityRulePortMax() != null) {
594             flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
595                     + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
596             matchBuilder = MatchUtils.createICMPv6Match(matchBuilder,
597                     portSecurityRule.getSecurityRulePortMin().shortValue(),
598                     portSecurityRule.getSecurityRulePortMax().shortValue());
599         } else {
600             /* All ICMP Match */ // We are getting from neutron NULL for both min and max
601             flowId = flowId + "all" + "_" ;
602             matchBuilder = MatchUtils.createICMPv6Match(matchBuilder, MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
603         }
604         if (null != dstAddress) {
605             flowId = flowId + dstAddress;
606             matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
607                     MatchUtils.iPv6PrefixFromIPv6Address(dstAddress));
608         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
609             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
610             matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
611                     new Ipv6Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
612         }
613         flowId = flowId + "_Permit";
614         addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
615         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
616         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority, matchBuilder, getTable());
617         addInstructionWithConntrackCommit(flowBuilder, false);
618         syncFlow(flowBuilder ,nodeBuilder, write);
619     }
620
621     /**
622      * Creates a egress match with src macaddress. If dest address is specified
623      * destination specific match will be created. Otherwise a match with a
624      * CIDR will be created.
625      * @param dpidLong the dpid
626      * @param segmentationId the segmentation id
627      * @param srcMac the source mac address.
628      * @param portSecurityRule the security rule in the SG
629      * @param dstAddress the source IP address
630      * @param write add or delete
631      * @param protoPortMatchPriority the protocol match priroty
632      */
633     private void egressAclUdp(Long dpidLong, String segmentationId, String srcMac,
634                               NeutronSecurityRule portSecurityRule, String dstAddress,
635                               boolean write, Integer protoPortMatchPriority) {
636         boolean portRange = false;
637         MatchBuilder matchBuilder = new MatchBuilder();
638         String flowId = "Egress_UDP_" + segmentationId + "_" + srcMac + "_";
639         boolean isIpv6 = NeutronSecurityRule.ETHERTYPE_IPV6.equals(portSecurityRule.getSecurityRuleEthertype());
640         if (isIpv6) {
641             matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null);
642         } else {
643             matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null,MatchUtils.ETHERTYPE_IPV4);
644         }
645
646         /* Custom UDP Match */
647         if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
648             flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
649             matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0,
650                                                      portSecurityRule.getSecurityRulePortMin());
651         } else {
652             /* All UDP Match */
653             if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
654                     && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
655                 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
656                     + portSecurityRule.getSecurityRulePortMax() + "_";
657                 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0, 0);
658             } else {
659                 portRange = true;
660             }
661         }
662         if (null != dstAddress) {
663             flowId = flowId + dstAddress;
664             if (isIpv6) {
665                 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null,
666                         MatchUtils.iPv6PrefixFromIPv6Address(dstAddress));
667             } else {
668                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
669                         MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
670             }
671         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
672             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
673             if (isIpv6) {
674                 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder, null,
675                         new Ipv6Prefix(portSecurityRule
676                                        .getSecurityRuleRemoteIpPrefix()));
677             } else {
678                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
679                         new Ipv4Prefix(portSecurityRule
680                                        .getSecurityRuleRemoteIpPrefix()));
681             }
682         }
683         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
684         if (portRange) {
685             Map<Integer, Integer> portMaskMap = MatchUtils
686                     .getLayer4MaskForRange(portSecurityRule.getSecurityRulePortMin(),
687                                            portSecurityRule.getSecurityRulePortMax());
688             for (Integer port: portMaskMap.keySet()) {
689                 String rangeflowId = flowId + port + "_" + portMaskMap.get(port) + "_";
690                 rangeflowId = rangeflowId + "_Permit";
691                 MatchUtils.addLayer4MatchWithMask(matchBuilder, MatchUtils.UDP_SHORT,
692                                                   0, port, portMaskMap.get(port));
693                 addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
694                 FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(rangeflowId, protoPortMatchPriority,
695                                                                       matchBuilder, getTable());
696                 addInstructionWithConntrackCommit(flowBuilder, false);
697                 syncFlow(flowBuilder ,nodeBuilder, write);
698             }
699         } else {
700             flowId = flowId + "_Permit";
701             addConntrackMatch(matchBuilder, MatchUtils.TRACKED_NEW_CT_STATE,MatchUtils.TRACKED_NEW_CT_STATE_MASK);
702             FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowId, protoPortMatchPriority,
703                                                                   matchBuilder, getTable());
704             addInstructionWithConntrackCommit(flowBuilder, false);
705             syncFlow(flowBuilder ,nodeBuilder, write);
706         }
707     }
708
709     /**
710      * Adds flow to allow any DHCP client traffic.
711      *
712      * @param dpidLong the dpid
713      * @param write whether to write or delete the flow
714      * @param localPort the local port.
715      * @param priority the priority
716      */
717     private void egressAclDhcpAllowClientTrafficFromVm(Long dpidLong,
718                                                        boolean write, long localPort, Integer priority) {
719         String flowName = "Egress_DHCP_Client"  + "_Permit_";
720         MatchBuilder matchBuilder = new MatchBuilder();
721         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
722         MatchUtils.createDhcpMatch(matchBuilder, DHCP_DESTINATION_PORT, DHCP_SOURCE_PORT);
723         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
724         addPipelineInstruction(flowBuilder, null, false);
725         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
726         syncFlow(flowBuilder ,nodeBuilder, write);
727     }
728
729     /**
730      * Adds flow to allow any DHCP IPv6 client traffic.
731      *
732      * @param dpidLong the dpid
733      * @param write whether to write or delete the flow
734      * @param localPort the local port
735      * @param priority the priority
736      */
737     private void egressAclDhcpv6AllowClientTrafficFromVm(Long dpidLong,
738                                                          boolean write, long localPort, Integer priority) {
739         String flowName = "Egress_DHCPv6_Client"  + "_Permit_";
740         MatchBuilder matchBuilder = new MatchBuilder();
741         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
742         MatchUtils.createDhcpv6Match(matchBuilder, DHCPV6_DESTINATION_PORT, DHCPV6_SOURCE_PORT);
743         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
744         addPipelineInstruction(flowBuilder, null, false);
745         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
746         syncFlow(flowBuilder ,nodeBuilder, write);
747     }
748
749     /**
750      * Adds rule to prevent DHCP spoofing by the vm attached to the port.
751      *
752      * @param dpidLong the dpid
753      * @param localPort the local port
754      * @param write is write or delete
755      * @param priority  the priority
756      */
757     private void egressAclDhcpDropServerTrafficfromVm(Long dpidLong, long localPort,
758                                                       boolean write, Integer priority) {
759         String flowName = "Egress_DHCP_Server" + "_" + localPort + "_DROP_";
760         MatchBuilder matchBuilder = new MatchBuilder();
761         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
762         MatchUtils.createDhcpMatch(matchBuilder, DHCP_SOURCE_PORT, DHCP_DESTINATION_PORT);
763         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
764         addPipelineInstruction(flowBuilder, null, true);
765         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
766         syncFlow(flowBuilder ,nodeBuilder, write);
767     }
768
769     /**
770      * Adds rule to prevent DHCPv6 spoofing by the vm attached to the port.
771      *
772      * @param dpidLong the dpid
773      * @param localPort the local port
774      * @param write is write or delete
775      * @param priority  the priority
776      */
777     private void egressAclDhcpv6DropServerTrafficfromVm(Long dpidLong, long localPort,
778                                                         boolean write, Integer priority) {
779
780         String flowName = "Egress_DHCPv6_Server" + "_" + localPort + "_DROP_";
781         MatchBuilder matchBuilder = new MatchBuilder();
782         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
783         MatchUtils.createDhcpv6Match(matchBuilder, DHCPV6_SOURCE_PORT, DHCPV6_DESTINATION_PORT);
784         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
785         addPipelineInstruction(flowBuilder, null, true);
786         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
787         syncFlow(flowBuilder ,nodeBuilder, write);
788     }
789
790     /**
791      * Adds rule to check legitimate ip/mac pair for each packet from the vm.
792      *
793      * @param dpidLong the dpid
794      * @param localPort the local port
795      * @param srcIp the vm ip address
796      * @param attachedMac the vm mac address
797      * @param priority  the priority
798      * @param write is write or delete
799      */
800     private void egressAclAllowTrafficFromVmIpMacPair(Long dpidLong, long localPort,
801                                                       String attachedMac, String srcIp,
802                                                       Integer priority, boolean write) {
803         MatchBuilder matchBuilder = new MatchBuilder();
804         MatchUtils.createSrcL3Ipv4MatchWithMac(matchBuilder, new Ipv4Prefix(srcIp),new MacAddress(attachedMac));
805         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
806         LOG.debug("egressAclAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", matchBuilder);
807         String flowName = "Egress_Allow_VM_IP_MAC" + "_" + localPort + attachedMac + "_Permit_";
808         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
809         addPipelineInstruction(flowBuilder, null, false);
810         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
811         syncFlow(flowBuilder ,nodeBuilder, write);
812     }
813
814     /**
815      * Adds rule to check legitimate ip/mac pair for each packet from the vm.
816      *
817      * @param dpidLong the dpid
818      * @param localPort the local port
819      * @param srcIp the vm ip address
820      * @param attachedMac the vm mac address
821      * @param priority  the priority
822      * @param write is write or delete
823      */
824     private void egressAclAllowTrafficFromVmIpV6MacPair(Long dpidLong, long localPort,
825                                                         String attachedMac, String srcIp,
826                                                         Integer priority, boolean write) {
827         MatchBuilder matchBuilder = new MatchBuilder();
828         MatchUtils.createSrcL3Ipv6MatchWithMac(matchBuilder, new Ipv6Prefix(srcIp),new MacAddress(attachedMac));
829         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
830         LOG.debug("egressAclAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", matchBuilder);
831         String flowName = "Egress_Allow_VM_IPv6_MAC" + "_" + localPort + attachedMac + "_Permit_";
832         FlowBuilder flowBuilder = FlowUtils.createFlowBuilder(flowName, priority, matchBuilder, getTable());
833         addPipelineInstruction(flowBuilder, null, false);
834         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
835         syncFlow(flowBuilder ,nodeBuilder, write);
836     }
837
838     private void addConntrackMatch(MatchBuilder matchBuilder, int state, int mask) {
839         if (securityServicesManager.isConntrackEnabled()) {
840             MatchUtils.addCtState(matchBuilder, state, mask );
841         }
842
843     }
844
845     private FlowBuilder addInstructionWithConntrackCommit( FlowBuilder flowBuilder , boolean isDrop) {
846         InstructionBuilder instructionBuilder = null;
847         if (securityServicesManager.isConntrackEnabled()) {
848             Action conntrackAction = ActionUtils.nxConntrackAction(1, 0L, 0, (short)0xff);
849             instructionBuilder = InstructionUtils
850                     .createInstructionBuilder(ActionUtils.conntrackActionBuilder(conntrackAction), 1, false);
851         }
852         return addPipelineInstruction(flowBuilder,instructionBuilder, isDrop);
853     }
854
855     private FlowBuilder addInstructionWithConntrackRecirc( FlowBuilder flowBuilder) {
856         InstructionBuilder instructionBuilder = null;
857         if (securityServicesManager.isConntrackEnabled()) {
858             Action conntrackAction = ActionUtils.nxConntrackAction(0, 0L, 0, (short)0x0);
859
860             instructionBuilder = InstructionUtils
861                     .createInstructionBuilder(ActionUtils.conntrackActionBuilder(conntrackAction), 1, false);
862             List<Instruction> instructionsList = Lists.newArrayList();
863             instructionsList.add(instructionBuilder.build());
864             InstructionsBuilder isb = new InstructionsBuilder();
865             isb.setInstruction(instructionsList);
866             flowBuilder.setInstructions(isb.build());
867         }
868         return flowBuilder;
869     }
870
871     private FlowBuilder addPipelineInstruction( FlowBuilder flowBuilder ,
872                                                 InstructionBuilder instructionBuilder,boolean isDrop) {
873         InstructionBuilder pipeLineIndstructionBuilder = createPipleLineInstructionBuilder(isDrop);
874         List<Instruction> instructionsList = Lists.newArrayList();
875         instructionsList.add(pipeLineIndstructionBuilder.build());
876         if (null != instructionBuilder) {
877             instructionsList.add(instructionBuilder.build());
878         }
879         InstructionsBuilder isb = new InstructionsBuilder();
880         isb.setInstruction(instructionsList);
881         flowBuilder.setInstructions(isb.build());
882         return flowBuilder;
883     }
884
885     private InstructionBuilder createPipleLineInstructionBuilder(boolean drop) {
886         InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
887         if (drop) {
888             InstructionUtils.createDropInstructions(ib);
889         }
890         ib.setOrder(0);
891         List<Instruction> instructionsList = Lists.newArrayList();
892         ib.setKey(new InstructionKey(0));
893         instructionsList.add(ib.build());
894         return ib;
895     }
896     /**
897      * Add or remove flow to the node.
898      * @param flowBuilder the flow builder
899      * @param nodeBuilder the node builder
900      * @param write whether it is a write
901      */
902     private void syncFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder,
903                           boolean write) {
904         if (write) {
905             writeFlow(flowBuilder, nodeBuilder);
906         } else {
907             removeFlow(flowBuilder, nodeBuilder);
908         }
909     }
910
911     private List<NeutronSecurityRule> getSecurityRulesforGroup(NeutronSecurityGroup securityGroup) {
912         List<NeutronSecurityRule> securityRules = new ArrayList<>();
913         List<NeutronSecurityRule> rules = neutronSecurityRule.getAllNeutronSecurityRules();
914         for (NeutronSecurityRule securityRule : rules) {
915             if (securityGroup.getID().equals(securityRule.getSecurityRuleGroupID())) {
916                 securityRules.add(securityRule);
917             }
918         }
919         return securityRules;
920     }
921
922     @Override
923     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
924         super.setDependencies(bundleContext.getServiceReference(EgressAclProvider.class.getName()), this);
925         securityServicesManager =
926                 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
927         securityGroupCacheManger =
928                 (SecurityGroupCacheManger) ServiceHelper.getGlobalInstance(SecurityGroupCacheManger.class, this);
929         neutronSecurityRule = (INeutronSecurityRuleCRUD) ServiceHelper.getGlobalInstance(INeutronSecurityRuleCRUD.class, this);
930     }
931
932     @Override
933     public void setDependencies(Object impl) {}
934 }