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