IPv6 support in Security Groups.
[ovsdb.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / providers / openflow13 / services / IngressAclService.java
1 /*
2  * Copyright (c) 2014, 2015 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.ovsdb.openstack.netvirt.providers.openflow13.services;
10
11 import com.google.common.collect.Lists;
12
13 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
14 import org.opendaylight.ovsdb.openstack.netvirt.api.IngressAclProvider;
15 import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityGroupCacheManger;
16 import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
17 import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
18 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
19 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
20 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityGroup;
21 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityRule;
22 import org.opendaylight.ovsdb.openstack.netvirt.translator.Neutron_IPs;
23 import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
24 import org.opendaylight.ovsdb.utils.mdsal.openflow.FlowUtils;
25 import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
26 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
27 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefixBuilder;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
53 import org.osgi.framework.BundleContext;
54 import org.osgi.framework.ServiceReference;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58 import java.math.BigInteger;
59 import java.net.Inet6Address;
60 import java.net.InetAddress;
61 import java.net.UnknownHostException;
62 import java.util.List;
63 import java.util.Map;
64
65 public class IngressAclService extends AbstractServiceInstance implements IngressAclProvider, ConfigInterface {
66     private static final Logger LOG = LoggerFactory.getLogger(IngressAclService.class);
67     private volatile SecurityServicesManager securityServicesManager;
68     private volatile SecurityGroupCacheManger securityGroupCacheManger;
69     private static final int PORT_RANGE_MIN = 1;
70     private static final int PORT_RANGE_MAX = 65535;
71
72     public IngressAclService() {
73         super(Service.INGRESS_ACL);
74     }
75
76     public IngressAclService(Service service) {
77         super(service);
78     }
79
80     @Override
81     public void programPortSecurityGroup(Long dpid, String segmentationId, String attachedMac,
82                                        long localPort, NeutronSecurityGroup securityGroup,
83                                        String portUuid, boolean write) {
84
85         LOG.trace("programPortSecurityGroup neutronSecurityGroup: {} ", securityGroup);
86         if (securityGroup == null || securityGroup.getSecurityRules() == null) {
87             return;
88         }
89
90         List<NeutronSecurityRule> portSecurityList = securityGroup.getSecurityRules();
91         /* Iterate over the Port Security Rules in the Port Security Group bound to the port*/
92         for (NeutronSecurityRule portSecurityRule : portSecurityList) {
93
94             /**
95              * Neutron Port Security Acl "ingress" and "IPv4"
96              * Check that the base conditions for flow based Port Security are true:
97              * Port Security Rule Direction ("ingress") and Protocol ("IPv4")
98              * Neutron defines the direction "ingress" as the vSwitch to the VM as defined in:
99              * http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html
100              *
101              */
102
103             if (portSecurityRule == null ||
104                     portSecurityRule.getSecurityRuleEthertype() == null ||
105                     portSecurityRule.getSecurityRuleDirection() == null) {
106                 continue;
107             }
108
109             if ("ingress".equals(portSecurityRule.getSecurityRuleDirection())) {
110                 LOG.debug("programPortSecurityGroup: Rule matching IP and ingress is: {} ", portSecurityRule);
111                 if (null != portSecurityRule.getSecurityRemoteGroupID()) {
112                     //Remote Security group is selected
113                     List<Neutron_IPs> remoteSrcAddressList = securityServicesManager
114                             .getVmListForSecurityGroup(portUuid,portSecurityRule.getSecurityRemoteGroupID());
115                     if (null != remoteSrcAddressList) {
116                         for (Neutron_IPs vmIp :remoteSrcAddressList ) {
117                             programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
118                                                     portSecurityRule, vmIp, write);
119                         }
120                         if (write) {
121                             securityGroupCacheManger.addToCache(portSecurityRule.getSecurityRemoteGroupID(), portUuid);
122                         } else {
123                             securityGroupCacheManger.removeFromCache(portSecurityRule.getSecurityRemoteGroupID(),
124                                                                      portUuid);
125                         }
126                     }
127                 } else {
128                     programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
129                                             portSecurityRule, null, write);
130                 }
131                 if (write) {
132                     securityGroupCacheManger.portAdded(securityGroup.getSecurityGroupUUID(), portUuid);
133                 } else {
134                     securityGroupCacheManger.portRemoved(securityGroup.getSecurityGroupUUID(), portUuid);
135                 }
136             }
137         }
138     }
139
140     @Override
141     public void programPortSecurityRule(Long dpid, String segmentationId, String attachedMac,
142                                         long localPort, NeutronSecurityRule portSecurityRule,
143                                         Neutron_IPs vmIp, boolean write) {
144         if (null == portSecurityRule.getSecurityRuleProtocol()) {
145             boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6");
146             ingressAclIP(dpid, isIpv6, segmentationId, attachedMac,
147                          write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
148         } else {
149             String ipaddress = null;
150             if (null != vmIp) {
151                 ipaddress = vmIp.getIpAddress();
152             } 
153
154             switch (portSecurityRule.getSecurityRuleProtocol()) {
155               case MatchUtils.TCP:
156                   LOG.debug("programPortSecurityRule: Rule matching TCP", portSecurityRule);
157                   ingressAclTcp(dpid, segmentationId, attachedMac, portSecurityRule, ipaddress,
158                               write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
159                   break;
160               case MatchUtils.UDP:
161                   LOG.debug("programPortSecurityRule: Rule matching UDP", portSecurityRule);
162                   ingressAclUdp(dpid, segmentationId, attachedMac, portSecurityRule, ipaddress,
163                                 write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
164                   break;
165               case MatchUtils.ICMP:
166               case MatchUtils.ICMPV6:
167                   LOG.debug("programPortSecurityRule: Rule matching ICMP", portSecurityRule);
168                   ingressAclIcmp(dpid, segmentationId, attachedMac, portSecurityRule, ipaddress,
169                                  write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
170                   break;
171               default:
172                   LOG.info("programPortSecurityAcl: Protocol is not TCP/UDP/ICMP but other " +
173                           "protocol = ", portSecurityRule.getSecurityRuleProtocol());
174                   ingressOtherProtocolAclHandler(dpid, segmentationId, attachedMac, portSecurityRule,
175                               null, write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
176                   break;
177             }
178         }
179     }
180
181     private void ingressOtherProtocolAclHandler(Long dpidLong, String segmentationId, String dstMac,
182           NeutronSecurityRule portSecurityRule, String srcAddress,
183           boolean write, Integer protoPortMatchPriority) {
184
185           MatchBuilder matchBuilder = new MatchBuilder();
186           String flowId = "Ingress_Other_" + segmentationId + "_" + dstMac + "_";
187           matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,dstMac);
188           short proto = 0;
189           try {
190               Integer protocol = new Integer(portSecurityRule.getSecurityRuleProtocol());
191               proto = protocol.shortValue();
192               flowId = flowId + proto;
193           } catch (NumberFormatException e) {
194               LOG.error("Protocol vlaue conversion failure", e);
195           }
196           matchBuilder = MatchUtils.createIpProtocolMatch(matchBuilder, proto);
197           if (null != srcAddress) {
198               flowId = flowId + srcAddress;
199               matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
200                                         MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null);
201           } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
202               flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
203               matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
204                                         new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()),null);
205           }
206           NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
207           flowId = flowId + "_Permit";
208           syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
209     }
210
211     @Override
212     public void programFixedSecurityGroup(Long dpid, String segmentationId, String dhcpMacAddress,
213                                         long localPort, boolean isLastPortinSubnet,
214                                         boolean isComputePort, String attachMac, boolean write) {
215         //If this port is the only port in the compute node add the DHCP server rule.
216         if (isLastPortinSubnet && isComputePort ) {
217             ingressAclDhcpAllowServerTraffic(dpid, segmentationId,dhcpMacAddress,
218                                              write,Constants.PROTO_DHCP_SERVER_MATCH_PRIORITY);
219             ingressAclDhcpv6AllowServerTraffic(dpid, segmentationId,dhcpMacAddress,
220                                                write,Constants.PROTO_DHCP_SERVER_MATCH_PRIORITY);
221         }
222         if (isComputePort) {
223             if (securityServicesManager.isConntrackEnabled()) {
224                 programIngressAclFixedConntrackRule(dpid, segmentationId, attachMac, localPort, write);
225             }
226             programArpRule(dpid, segmentationId, localPort, attachMac, write);
227         }
228     }
229
230     private void programArpRule(Long dpid, String segmentationId, long localPort, String attachMac, boolean write) {
231         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
232         MatchBuilder matchBuilder = new MatchBuilder();
233         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
234         String flowId = "Ingress_ARP_" + segmentationId + "_" + localPort + "_";
235         EthernetMatchBuilder ethernetType = new EthernetMatchBuilder();
236         EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
237         ethTypeBuilder.setType(new EtherType(0x0806L));
238         ethernetType.setEthernetType(ethTypeBuilder.build());
239         matchBuilder.setEthernetMatch(ethernetType.build());
240
241         ArpMatchBuilder arpDstMatch = new ArpMatchBuilder();
242         ArpTargetHardwareAddressBuilder arpDst = new ArpTargetHardwareAddressBuilder();
243         arpDst.setAddress(new MacAddress(attachMac));
244         arpDstMatch.setArpTargetHardwareAddress(arpDst.build());
245         matchBuilder.setLayer3Match(arpDstMatch.build());
246         syncFlow(flowId, nodeBuilder, matchBuilder, Constants.PROTO_MATCH_PRIORITY, write, false, securityServicesManager.isConntrackEnabled());
247     }
248
249     private void programIngressAclFixedConntrackRule(Long dpid,
250            String segmentationId, String attachMac, long localPort, boolean write) {
251         try {
252             String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpid;
253             programConntrackUntrackRule(nodeName, segmentationId, localPort, attachMac,
254                                         Constants.CT_STATE_UNTRACKED_PRIORITY, write );
255             programConntrackTrackedPlusEstRule(nodeName, segmentationId, localPort, attachMac,
256                                         Constants.CT_STATE_TRACKED_EST_PRIORITY, write );
257             programConntrackNewDropRule(nodeName, segmentationId, localPort, attachMac,
258                                              Constants.CT_STATE_NEW_PRIORITY_DROP, write );
259             LOG.info("programIngressAclFixedConntrackRule :  default connection tracking rule are added.");
260         } catch (Exception e) {
261             LOG.error("Failed to add default conntrack rules : " , e);
262         }
263     }
264
265     private void programConntrackUntrackRule(String nodeName, String segmentationId,
266                                              long localPort, String attachMac, Integer priority, boolean write) {
267         MatchBuilder matchBuilder = new MatchBuilder();
268         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
269         String flowName = "Ingress_Fixed_Conntrk_Untrk_" + segmentationId + "_" + localPort + "_";
270         matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,attachMac);
271         matchBuilder = MatchUtils.addCtState(matchBuilder,0x00, 0x80);
272         FlowBuilder flowBuilder = new FlowBuilder();
273         flowBuilder.setMatch(matchBuilder.build());
274         FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
275         if (write) {
276             InstructionBuilder ib = new InstructionBuilder();
277             List<Instruction> instructionsList = Lists.newArrayList();
278             InstructionsBuilder isb = new InstructionsBuilder();
279             ActionBuilder ab = new ActionBuilder();
280             ab.setAction(ActionUtils.nxConntrackAction(0, 0L, 0, (short)0x0));
281             // 0xff means no table, 0x0 is table = 0
282             // nxConntrackAction(Integer flags, Long zoneSrc,Integer conntrackZone, Short recircTable)
283             ab.setOrder(0);
284             ab.setKey(new ActionKey(0));
285             List<Action> actionList = Lists.newArrayList();
286             actionList.add(ab.build());
287             ApplyActionsBuilder aab = new ApplyActionsBuilder();
288             aab.setAction(actionList);
289
290             ib.setOrder(0);
291             ib.setKey(new InstructionKey(0));
292             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
293             instructionsList.add(ib.build());
294             isb.setInstruction(instructionsList);
295             flowBuilder.setInstructions(isb.build());
296             writeFlow(flowBuilder, nodeBuilder);
297             LOG.info("INGRESS:default programConntrackUntrackRule() flows are written");
298         } else {
299             removeFlow(flowBuilder, nodeBuilder);
300         }
301     }
302
303     private void programConntrackTrackedPlusEstRule(String nodeName, String segmentationId,
304                                                   long localPort, String attachMac,Integer priority, boolean write) {
305         MatchBuilder matchBuilder = new MatchBuilder();
306         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
307         String flowName = "Ingress_Fixed_Conntrk_TrkEst_" + segmentationId + "_" + localPort + "_";
308         matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,attachMac);
309         matchBuilder = MatchUtils.addCtState(matchBuilder,0x82, 0x82);
310         FlowBuilder flowBuilder = new FlowBuilder();
311         flowBuilder.setMatch(matchBuilder.build());
312         FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
313         if (write) {
314             InstructionBuilder ib = new InstructionBuilder();
315             List<Instruction> instructionsList = Lists.newArrayList();
316             InstructionsBuilder isb = new InstructionsBuilder();
317
318             ib = this.getMutablePipelineInstructionBuilder();
319             ib.setOrder(0);
320             ib.setKey(new InstructionKey(0));
321             instructionsList.add(ib.build());
322              isb.setInstruction(instructionsList);
323             flowBuilder.setInstructions(isb.build());
324             writeFlow(flowBuilder, nodeBuilder);
325             LOG.info("INGRESS:default programConntrackTrackedPlusEstRule() flows are written");
326         } else {
327             removeFlow(flowBuilder, nodeBuilder);
328         }
329     }
330
331     private void programConntrackNewDropRule(String nodeName, String segmentationId,
332                                              long localPort, String attachMac, Integer priority, boolean write) {
333         MatchBuilder matchBuilder = new MatchBuilder();
334         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
335         String flowName = "Ingress_Fixed_Conntrk_NewDrop_" + segmentationId + "_" + localPort + "_";
336         matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,attachMac);
337         matchBuilder = MatchUtils.addCtState(matchBuilder,0x01, 0x01);
338         FlowBuilder flowBuilder = new FlowBuilder();
339         flowBuilder.setMatch(matchBuilder.build());
340         FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
341         if (write) {
342             // Instantiate the Builders for the OF Actions and Instructions
343             InstructionBuilder ib = new InstructionBuilder();
344             InstructionsBuilder isb = new InstructionsBuilder();
345
346             // Instructions List Stores Individual Instructions
347             List<Instruction> instructions = Lists.newArrayList();
348
349             // Set the Output Port/Iface
350             InstructionUtils.createDropInstructions(ib);
351             ib.setOrder(0);
352             ib.setKey(new InstructionKey(0));
353             instructions.add(ib.build());
354
355             // Add InstructionBuilder to the Instruction(s)Builder List
356             isb.setInstruction(instructions);
357             LOG.debug("Instructions contain: {}", ib.getInstruction());
358             // Add InstructionsBuilder to FlowBuilder
359             flowBuilder.setInstructions(isb.build());
360             writeFlow(flowBuilder, nodeBuilder);
361             LOG.info("INGRESS:default programConntrackNewDropRule flows are written");
362         } else {
363             removeFlow(flowBuilder, nodeBuilder);
364         }
365     }
366
367     /**
368      * Allows an IPv4/v6 packet ingress to the destination mac address.
369      * @param dpidLong the dpid
370      * @param segmentationId the segementation id
371      * @param dstMac the destination mac address
372      * @param write add or remove
373      * @param protoPortMatchPriority the protocol match priority.
374      */
375     private void ingressAclIP(Long dpidLong, boolean isIpv6, String segmentationId, String dstMac,
376                               boolean write, Integer protoPortMatchPriority ) {
377         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
378         MatchBuilder matchBuilder = new MatchBuilder();
379         String flowId = "Ingress_IP" + segmentationId + "_" + dstMac + "_Permit_";
380         if (isIpv6) {
381             matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,null,dstMac);
382         }else {
383             matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,dstMac);
384         }
385         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
386     }
387
388     /**
389      * Creates a ingress match to the dst macaddress. If src address is specified
390      * source specific match will be created. Otherwise a match with a CIDR will
391      * be created.
392      * @param dpidLong the dpid
393      * @param segmentationId the segmentation id
394      * @param dstMac the destination mac address.
395      * @param portSecurityRule the security rule in the SG
396      * @param srcAddress the destination IP address
397      * @param write add or delete
398      * @param protoPortMatchPriority the protocol match priroty
399      */
400     private void ingressAclTcp(Long dpidLong, String segmentationId, String dstMac,
401                                NeutronSecurityRule portSecurityRule, String srcAddress, boolean write,
402                                Integer protoPortMatchPriority ) {
403         boolean portRange = false;
404         MatchBuilder matchBuilder = new MatchBuilder();
405         String flowId = "Ingress_TCP_" + segmentationId + "_" + dstMac + "_";
406         boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6");
407         if (isIpv6) {
408             matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,null,dstMac);
409         } else {
410             matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,dstMac);
411         }
412
413         /* Custom TCP Match*/
414         if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
415             flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
416             matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0,
417                                                      portSecurityRule.getSecurityRulePortMin());
418         } else {
419             /* All TCP Match */
420             if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
421                     && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
422                 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
423                     + portSecurityRule.getSecurityRulePortMax() + "_";
424                 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0, 0);
425             } else {
426                 portRange = true;
427             }
428         }
429         if (null != srcAddress) {
430             flowId = flowId + srcAddress;
431             if (isIpv6) {
432                 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,
433                         MatchUtils.iPv6PrefixFromIPv6Address(srcAddress),null);
434             } else {
435                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
436                         MatchUtils.iPv4PrefixFromIPv4Address(srcAddress),null);
437             }
438         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
439             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
440             if (isIpv6) {
441                 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,
442                         new Ipv6Prefix(portSecurityRule
443                                        .getSecurityRuleRemoteIpPrefix()),null);
444             } else {
445                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
446                         new Ipv4Prefix(portSecurityRule
447                                        .getSecurityRuleRemoteIpPrefix()),null);
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                 syncFlow(rangeflowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
461             }
462         } else {
463             flowId = flowId + "_Permit";
464             syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
465         }
466     }
467
468     /**
469      * Creates a ingress match to the dst macaddress. If src address is specified
470      * source specific match will be created. Otherwise a match with a CIDR will
471      * be created.
472      * @param dpidLong the dpid
473      * @param segmentationId the segmentation id
474      * @param dstMac the destination mac address.
475      * @param portSecurityRule the security rule in the SG
476      * @param srcAddress the destination IP address
477      * @param write add or delete
478      * @param protoPortMatchPriority the protocol match priroty
479      */
480     private void ingressAclUdp(Long dpidLong, String segmentationId, String dstMac,
481                                NeutronSecurityRule portSecurityRule, String srcAddress,
482                                boolean write, Integer protoPortMatchPriority ) {
483         boolean portRange = false;
484         boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6");
485         MatchBuilder matchBuilder = new MatchBuilder();
486         String flowId = "Ingress_UDP_" + segmentationId + "_" + dstMac + "_";
487         if (isIpv6)  {
488             matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,null,dstMac);
489         }else {
490             matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,dstMac);
491         }
492
493         /* Custom UDP Match */
494         if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
495             flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
496             matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0,
497                                                      portSecurityRule.getSecurityRulePortMin());
498         } else {
499             /* All UDP Match */
500             if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
501                     && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
502                 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
503                     + portSecurityRule.getSecurityRulePortMax() + "_";
504                 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0, 0);
505             } else {
506                 portRange = true;
507             }
508         }
509         if (null != srcAddress) {
510             flowId = flowId + srcAddress;
511             if (isIpv6) {
512                 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,
513                         MatchUtils.iPv6PrefixFromIPv6Address(srcAddress), null);
514             } else {
515                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
516                         MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null);
517             }
518         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
519             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
520             if (isIpv6) {
521                 matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,
522                         new Ipv6Prefix(portSecurityRule
523                                        .getSecurityRuleRemoteIpPrefix()),null);
524             } else {
525                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
526                         new Ipv4Prefix(portSecurityRule
527                                        .getSecurityRuleRemoteIpPrefix()),null);
528             }
529         }
530         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
531         if (portRange) {
532             Map<Integer, Integer> portMaskMap = MatchUtils
533                     .getLayer4MaskForRange(portSecurityRule.getSecurityRulePortMin(),
534                                            portSecurityRule.getSecurityRulePortMax());
535             for (Integer port: portMaskMap.keySet()) {
536                 String rangeflowId = flowId + port + "_" + portMaskMap.get(port) + "_";
537                 rangeflowId = rangeflowId + "_Permit";
538                 MatchUtils.addLayer4MatchWithMask(matchBuilder, MatchUtils.UDP_SHORT,
539                                                    0, port, portMaskMap.get(port));
540                 syncFlow(rangeflowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
541             }
542         } else {
543             flowId = flowId + "_Permit";
544             syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
545         }
546     }
547
548     private void ingressAclIcmp(Long dpidLong, String segmentationId, String dstMac,
549             NeutronSecurityRule portSecurityRule, String srcAddress,
550             boolean write, Integer protoPortMatchPriority) {
551
552         boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6");
553         if (isIpv6) {
554             ingressAclIcmpV6(dpidLong, segmentationId, dstMac, portSecurityRule, srcAddress, write, protoPortMatchPriority);
555         } else {
556             ingressAclIcmpV4(dpidLong, segmentationId, dstMac, portSecurityRule, srcAddress, write, protoPortMatchPriority);
557         }
558     }
559
560     /**
561      * Creates a ingress icmp match to the dst macaddress. If src address is specified
562      * source specific match will be created. Otherwise a match with a CIDR will
563      * be created.
564      * @param dpidLong the dpid
565      * @param segmentationId the segmentation id
566      * @param dstMac the destination mac address.
567      * @param portSecurityRule the security rule in the SG
568      * @param srcAddress the destination IP address
569      * @param write add or delete
570      * @param protoPortMatchPriority the protocol match priority
571      */
572     private void ingressAclIcmpV4(Long dpidLong, String segmentationId, String dstMac,
573                                   NeutronSecurityRule portSecurityRule, String srcAddress,
574                                   boolean write, Integer protoPortMatchPriority) {
575
576         MatchBuilder matchBuilder = new MatchBuilder();
577         String flowId = "Ingress_ICMP_" + segmentationId + "_" + dstMac + "_";
578         matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,dstMac);
579
580         /* Custom ICMP Match */
581         if (portSecurityRule.getSecurityRulePortMin() != null &&
582                 portSecurityRule.getSecurityRulePortMax() != null) {
583             flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
584                     + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
585             matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,
586                     portSecurityRule.getSecurityRulePortMin().shortValue(),
587                     portSecurityRule.getSecurityRulePortMax().shortValue());
588         } else {
589             /* All ICMP Match */
590             flowId = flowId + "all" + "_";
591             matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
592         }
593         if (null != srcAddress) {
594             flowId = flowId + srcAddress;
595             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
596                    MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null);
597         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
598             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
599             if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) {
600                 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
601                                          new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()),null);
602             }
603         }
604         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
605         flowId = flowId + "_Permit";
606         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled());
607     }
608
609     /**
610      * Creates a ingress icmpv6 match to the dst macaddress. If src address is specified
611      * source specific match will be created. Otherwise a match with a CIDR will
612      * be created.
613      * @param dpidLong the dpid
614      * @param segmentationId the segmentation id
615      * @param dstMac the destination mac address.
616      * @param portSecurityRule the security rule in the SG
617      * @param srcAddress the destination IP address
618      * @param write add or delete
619      * @param protoPortMatchPriority the protocol match priority
620      */
621     private void ingressAclIcmpV6(Long dpidLong, String segmentationId, String dstMac,
622                                   NeutronSecurityRule portSecurityRule, String srcAddress,
623                                   boolean write, Integer protoPortMatchPriority) {
624
625         MatchBuilder matchBuilder = new MatchBuilder();
626         String flowId = "Ingress_ICMP_" + segmentationId + "_" + dstMac + "_";
627         matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,null,dstMac);
628
629         /* Custom ICMP Match */
630         if (portSecurityRule.getSecurityRulePortMin() != null &&
631                 portSecurityRule.getSecurityRulePortMax() != null) {
632             flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
633                     + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
634             matchBuilder = MatchUtils.createICMPv6Match(matchBuilder,
635                     portSecurityRule.getSecurityRulePortMin().shortValue(),
636                     portSecurityRule.getSecurityRulePortMax().shortValue());
637         } else {
638             /* All ICMP Match */
639             flowId = flowId + "all" + "_";
640             matchBuilder = MatchUtils.createICMPv6Match(matchBuilder,MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
641         }
642         if (null != srcAddress) {
643             flowId = flowId + srcAddress;
644             matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,
645                     MatchUtils.iPv6PrefixFromIPv6Address(srcAddress), null);
646         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
647             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
648             matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,
649                     new Ipv6Prefix(portSecurityRule
650                                    .getSecurityRuleRemoteIpPrefix()),null);
651         }
652         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
653         flowId = flowId + "_Permit";
654         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false);
655     }
656
657
658     public void ingressACLTcpSyn(Long dpidLong, String segmentationId, String attachedMac, boolean write,
659                                  Integer securityRulePortMin, Integer protoPortMatchPriority) {
660
661         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
662         PortNumber tcpPort = new PortNumber(securityRulePortMin);
663         MatchBuilder matchBuilder = new MatchBuilder();
664         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
665         FlowBuilder flowBuilder = new FlowBuilder();
666
667         flowBuilder.setMatch(MatchUtils.createDmacTcpSynMatch(matchBuilder, attachedMac, tcpPort,
668                                                               Constants.TCP_SYN, segmentationId).build());
669
670         LOG.debug("ingressACLTcpSyn MatchBuilder contains:  {}", flowBuilder.getMatch());
671         String flowId = "UcastOut_ACL2_" + segmentationId + "_" + attachedMac + securityRulePortMin;
672         // Add Flow Attributes
673         flowBuilder.setId(new FlowId(flowId));
674         FlowKey key = new FlowKey(new FlowId(flowId));
675         flowBuilder.setStrict(false);
676         flowBuilder.setPriority(protoPortMatchPriority);
677         flowBuilder.setBarrier(true);
678         flowBuilder.setTableId(this.getTable());
679         flowBuilder.setKey(key);
680         flowBuilder.setFlowName(flowId);
681         flowBuilder.setHardTimeout(0);
682         flowBuilder.setIdleTimeout(0);
683
684         if (write) {
685             // Instantiate the Builders for the OF Actions and Instructions
686             InstructionsBuilder isb = new InstructionsBuilder();
687             List<Instruction> instructionsList = Lists.newArrayList();
688
689             InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
690             ib.setOrder(0);
691             ib.setKey(new InstructionKey(0));
692             instructionsList.add(ib.build());
693             isb.setInstruction(instructionsList);
694
695             LOG.debug("Instructions are: {}", ib.getInstruction());
696             // Add InstructionsBuilder to FlowBuilder
697             flowBuilder.setInstructions(isb.build());
698             writeFlow(flowBuilder, nodeBuilder);
699         } else {
700             removeFlow(flowBuilder, nodeBuilder);
701         }
702     }
703
704     public void ingressACLTcpPortWithPrefix(Long dpidLong, String segmentationId, String attachedMac,
705                                             boolean write, Integer securityRulePortMin, String securityRuleIpPrefix,
706                                             Integer protoPortPrefixMatchPriority) {
707
708         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
709         PortNumber tcpPort = new PortNumber(securityRulePortMin);
710
711         MatchBuilder matchBuilder = new MatchBuilder();
712         NodeBuilder nodeBuilder = this.createNodeBuilder(nodeName);
713         FlowBuilder flowBuilder = new FlowBuilder();
714         Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
715
716         flowBuilder.setMatch(MatchUtils
717                              .createDmacTcpSynDstIpPrefixTcpPort(matchBuilder, new MacAddress(attachedMac),
718                                                                  tcpPort, Constants.TCP_SYN, segmentationId, srcIpPrefix).build());
719
720         LOG.debug(" MatchBuilder contains:  {}", flowBuilder.getMatch());
721         String flowId = "UcastOut2_" + segmentationId + "_" + attachedMac +
722                 securityRulePortMin + securityRuleIpPrefix;
723         // Add Flow Attributes
724         flowBuilder.setId(new FlowId(flowId));
725         FlowKey key = new FlowKey(new FlowId(flowId));
726         flowBuilder.setStrict(false);
727         flowBuilder.setPriority(protoPortPrefixMatchPriority);
728         flowBuilder.setBarrier(true);
729         flowBuilder.setTableId(this.getTable());
730         flowBuilder.setKey(key);
731         flowBuilder.setFlowName(flowId);
732         flowBuilder.setHardTimeout(0);
733         flowBuilder.setIdleTimeout(0);
734
735         if (write) {
736             // Instantiate the Builders for the OF Actions and Instructions
737             InstructionsBuilder isb = new InstructionsBuilder();
738
739             List<Instruction> instructionsList = Lists.newArrayList();
740             InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
741             ib.setOrder(0);
742             ib.setKey(new InstructionKey(0));
743             instructionsList.add(ib.build());
744             isb.setInstruction(instructionsList);
745
746             LOG.debug("Instructions contain: {}", ib.getInstruction());
747             // Add InstructionsBuilder to FlowBuilder
748             flowBuilder.setInstructions(isb.build());
749             writeFlow(flowBuilder, nodeBuilder);
750         } else {
751             removeFlow(flowBuilder, nodeBuilder);
752         }
753     }
754
755     public void handleIngressAllowProto(Long dpidLong, String segmentationId, String attachedMac, boolean write,
756                                         String securityRuleProtcol, Integer protoMatchPriority) {
757
758         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
759
760         MatchBuilder matchBuilder = new MatchBuilder();
761         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
762         FlowBuilder flowBuilder = new FlowBuilder();
763
764         flowBuilder.setMatch(MatchUtils
765                              .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null).build());
766         flowBuilder.setMatch(MatchUtils
767                              .createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
768         LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
769
770         String flowId = "UcastOut_" + segmentationId + "_" +
771                 attachedMac + "_AllowTCPSynPrefix_" + securityRuleProtcol;
772         // Add Flow Attributes
773         flowBuilder.setId(new FlowId(flowId));
774         FlowKey key = new FlowKey(new FlowId(flowId));
775         flowBuilder.setStrict(false);
776         flowBuilder.setPriority(protoMatchPriority);
777         flowBuilder.setBarrier(true);
778         flowBuilder.setTableId(this.getTable());
779         flowBuilder.setKey(key);
780         flowBuilder.setFlowName(flowId);
781         flowBuilder.setHardTimeout(0);
782         flowBuilder.setIdleTimeout(0);
783
784         if (write) {
785             // Instantiate the Builders for the OF Actions and Instructions
786             InstructionsBuilder isb = new InstructionsBuilder();
787             List<Instruction> instructionsList = Lists.newArrayList();
788
789             InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
790             ib.setOrder(1);
791             ib.setKey(new InstructionKey(1));
792             instructionsList.add(ib.build());
793             isb.setInstruction(instructionsList);
794             LOG.debug("Instructions contain: {}", ib.getInstruction());
795
796             // Add InstructionsBuilder to FlowBuilder
797             flowBuilder.setInstructions(isb.build());
798             writeFlow(flowBuilder, nodeBuilder);
799         } else {
800             removeFlow(flowBuilder, nodeBuilder);
801         }
802     }
803
804
805     public void ingressACLDefaultTcpDrop(Long dpidLong, String segmentationId, String attachedMac,
806                                          int priority, boolean write) {
807
808         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
809         MatchBuilder matchBuilder = new MatchBuilder();
810         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
811         FlowBuilder flowBuilder = new FlowBuilder();
812
813         flowBuilder.setMatch(MatchUtils.createDmacTcpPortWithFlagMatch(matchBuilder,
814                                                                        attachedMac, Constants.TCP_SYN, segmentationId).build());
815
816         LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
817         String flowId = "PortSec_TCP_Syn_Default_Drop_" + segmentationId + "_" + attachedMac;
818         flowBuilder.setId(new FlowId(flowId));
819         FlowKey key = new FlowKey(new FlowId(flowId));
820         flowBuilder.setStrict(false);
821         flowBuilder.setPriority(priority);
822         flowBuilder.setBarrier(true);
823         flowBuilder.setTableId(this.getTable());
824         flowBuilder.setKey(key);
825         flowBuilder.setFlowName(flowId);
826         flowBuilder.setHardTimeout(0);
827         flowBuilder.setIdleTimeout(0);
828
829         if (write) {
830             // Instantiate the Builders for the OF Actions and Instructions
831             InstructionBuilder ib = new InstructionBuilder();
832             InstructionsBuilder isb = new InstructionsBuilder();
833
834             // Instructions List Stores Individual Instructions
835             List<Instruction> instructions = Lists.newArrayList();
836
837             // Set the Output Port/Iface
838             InstructionUtils.createDropInstructions(ib);
839             ib.setOrder(0);
840             ib.setKey(new InstructionKey(0));
841             instructions.add(ib.build());
842
843             // Add InstructionBuilder to the Instruction(s)Builder List
844             isb.setInstruction(instructions);
845             LOG.debug("Instructions contain: {}", ib.getInstruction());
846             // Add InstructionsBuilder to FlowBuilder
847             flowBuilder.setInstructions(isb.build());
848             writeFlow(flowBuilder, nodeBuilder);
849         } else {
850             removeFlow(flowBuilder, nodeBuilder);
851         }
852     }
853
854     public void ingressACLPermitAllProto(Long dpidLong, String segmentationId, String attachedMac,
855                                          boolean write, String securityRuleIpPrefix, Integer protoPortMatchPriority) {
856         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
857         Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
858         MatchBuilder matchBuilder = new MatchBuilder();
859         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
860         FlowBuilder flowBuilder = new FlowBuilder();
861
862         flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId))
863                              .build());
864         if (securityRuleIpPrefix != null) {
865             flowBuilder.setMatch(MatchUtils
866                                  .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, srcIpPrefix)
867                                  .build());
868         } else {
869             flowBuilder.setMatch(MatchUtils
870                                  .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null)
871                                  .build());
872         }
873
874         LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
875         String flowId = "IngressProto_ACL_" + segmentationId + "_" +
876                 attachedMac + "_Permit_" + securityRuleIpPrefix;
877         // Add Flow Attributes
878         flowBuilder.setId(new FlowId(flowId));
879         FlowKey key = new FlowKey(new FlowId(flowId));
880         flowBuilder.setStrict(false);
881         flowBuilder.setPriority(protoPortMatchPriority);
882         flowBuilder.setBarrier(true);
883         flowBuilder.setTableId(this.getTable());
884         flowBuilder.setKey(key);
885         flowBuilder.setFlowName(flowId);
886         flowBuilder.setHardTimeout(0);
887         flowBuilder.setIdleTimeout(0);
888
889         if (write) {
890             // Instantiate the Builders for the OF Actions and Instructions
891             InstructionBuilder ib = new InstructionBuilder();
892             InstructionsBuilder isb = new InstructionsBuilder();
893             List<Instruction> instructionsList = Lists.newArrayList();
894
895             ib = this.getMutablePipelineInstructionBuilder();
896             ib.setOrder(1);
897             ib.setKey(new InstructionKey(0));
898             instructionsList.add(ib.build());
899             isb.setInstruction(instructionsList);
900
901             LOG.debug("Instructions contain: {}", ib.getInstruction());
902             // Add InstructionsBuilder to FlowBuilder
903             flowBuilder.setInstructions(isb.build());
904             writeFlow(flowBuilder, nodeBuilder);
905         } else {
906             removeFlow(flowBuilder, nodeBuilder);
907         }
908     }
909
910     /**
911      * Add rule to ensure only DHCP server traffic from the specified mac is allowed.
912      *
913      * @param dpidLong the dpid
914      * @param segmentationId the segmentation id
915      * @param dhcpMacAddress the DHCP server mac address
916      * @param write is write or delete
917      * @param protoPortMatchPriority the priority
918      */
919     private void ingressAclDhcpAllowServerTraffic(Long dpidLong, String segmentationId, String dhcpMacAddress,
920                                                   boolean write, Integer protoPortMatchPriority) {
921
922         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
923         MatchBuilder matchBuilder = new MatchBuilder();
924         MatchUtils.createDhcpServerMatch(matchBuilder, dhcpMacAddress, 67, 68).build();
925         String flowId = "Ingress_DHCP_Server" + segmentationId + "_" + dhcpMacAddress + "_Permit_";
926         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false);
927     }
928
929     /**
930      * Add rule to ensure only DHCPv6 server traffic from the specified mac is allowed.
931      *
932      * @param dpidLong the dpid
933      * @param segmentationId the segmentation id
934      * @param dhcpMacAddress the DHCP server mac address
935      * @param write is write or delete
936      * @param protoPortMatchPriority the priority
937      */
938     private void ingressAclDhcpv6AllowServerTraffic(Long dpidLong, String segmentationId, String dhcpMacAddress,
939                                                     boolean write, Integer protoPortMatchPriority) {
940
941         NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong);
942         MatchBuilder matchBuilder = new MatchBuilder();
943         MatchUtils.createDhcpv6ServerMatch(matchBuilder, dhcpMacAddress, 547, 546).build();
944         String flowId = "Ingress_DHCPv6_Server" + segmentationId + "_" + dhcpMacAddress + "_Permit_";
945         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false);
946     }
947
948     /**
949      * Add or remove flow to the node.
950      *
951      * @param flowName the the flow id
952      * @param nodeBuilder the node builder
953      * @param matchBuilder the matchbuilder
954      * @param priority the protocol priority
955      * @param write whether it is a write
956      * @param drop whether it is a drop or forward
957      * @param isCtCommit commit the connection or CT to track
958      */
959     private void syncFlow(String flowName, NodeBuilder nodeBuilder,
960                           MatchBuilder matchBuilder, Integer priority,
961                           boolean write, boolean drop, boolean isCtCommit) {
962         MatchBuilder matchBuilder1 = matchBuilder;
963         if (isCtCommit) {
964             matchBuilder1 = MatchUtils.addCtState(matchBuilder1,0x81, 0x81);
965         }
966         FlowBuilder flowBuilder = new FlowBuilder();
967         flowBuilder.setMatch(matchBuilder1.build());
968         FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable()).setPriority(priority);
969
970         if (write) {
971             InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
972             InstructionBuilder ib1 = new InstructionBuilder();
973             ActionBuilder ab = new ActionBuilder();
974             ApplyActionsBuilder aab = new ApplyActionsBuilder();
975             if (drop) {
976                 InstructionUtils.createDropInstructions(ib);
977             }
978             ib.setOrder(0);
979             InstructionsBuilder isb = new InstructionsBuilder();
980             List<Instruction> instructionsList = Lists.newArrayList();
981             ib.setKey(new InstructionKey(0));
982             instructionsList.add(ib.build());
983             if (isCtCommit) {
984                 LOG.info("Adding Conntarck rule, flowname = " + flowName);
985                 ab.setAction(ActionUtils.nxConntrackAction(1, 0L, 0, (short)0xff));
986                 ab.setOrder(0);
987                 ab.setKey(new ActionKey(0));
988                 List<Action> actionList = Lists.newArrayList();
989                 actionList.add(ab.build());
990                 aab.setAction(actionList);
991                 ib1.setOrder(1);
992                 ib1.setKey(new InstructionKey(1));
993                 ib1.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
994                 instructionsList.add(ib1.build());
995             }
996             isb.setInstruction(instructionsList);
997             flowBuilder.setInstructions(isb.build());
998             writeFlow(flowBuilder, nodeBuilder);
999         } else {
1000             removeFlow(flowBuilder, nodeBuilder);
1001         }
1002     }
1003
1004     @Override
1005     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
1006         super.setDependencies(bundleContext.getServiceReference(IngressAclProvider.class.getName()), this);
1007         securityServicesManager =
1008                 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
1009         securityGroupCacheManger =
1010                 (SecurityGroupCacheManger) ServiceHelper.getGlobalInstance(SecurityGroupCacheManger.class, this);
1011     }
1012
1013     @Override
1014     public void setDependencies(Object impl) {
1015
1016     }
1017 }