Avoid exceptions with IPv6 subnets
[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
12 import com.google.common.collect.Lists;
13
14 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
15 import org.opendaylight.ovsdb.openstack.netvirt.api.IngressAclProvider;
16 import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityGroupCacheManger;
17 import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
18 import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
19 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
20 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
21 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityGroup;
22 import org.opendaylight.ovsdb.openstack.netvirt.translator.NeutronSecurityRule;
23 import org.opendaylight.ovsdb.openstack.netvirt.translator.Neutron_IPs;
24 import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
25 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
26 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefixBuilder;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
41 import org.osgi.framework.BundleContext;
42 import org.osgi.framework.ServiceReference;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 import java.math.BigInteger;
47 import java.net.Inet6Address;
48 import java.net.InetAddress;
49 import java.net.UnknownHostException;
50 import java.util.List;
51
52
53
54 public class IngressAclService extends AbstractServiceInstance implements IngressAclProvider, ConfigInterface {
55
56     private static final Logger LOG = LoggerFactory.getLogger(IngressAclService.class);
57     private volatile SecurityServicesManager securityServicesManager;
58     private volatile SecurityGroupCacheManger securityGroupCacheManger;
59     private static final int PORT_RANGE_MIN = 1;
60     private static final int PORT_RANGE_MAX = 65535;
61
62     public IngressAclService() {
63         super(Service.INGRESS_ACL);
64     }
65
66     public IngressAclService(Service service) {
67         super(service);
68     }
69
70     @Override
71     public void programPortSecurityGroup(Long dpid, String segmentationId, String attachedMac,
72                                        long localPort, NeutronSecurityGroup securityGroup,
73                                        String portUuid, boolean write) {
74
75         LOG.trace("programPortSecurityGroup neutronSecurityGroup: {} ", securityGroup);
76         if (securityGroup == null || securityGroup.getSecurityRules() == null) {
77             return;
78         }
79
80         List<NeutronSecurityRule> portSecurityList = securityGroup.getSecurityRules();
81         /* Iterate over the Port Security Rules in the Port Security Group bound to the port*/
82         for (NeutronSecurityRule portSecurityRule : portSecurityList) {
83
84             /**
85              * Neutron Port Security Acl "ingress" and "IPv4"
86              * Check that the base conditions for flow based Port Security are true:
87              * Port Security Rule Direction ("ingress") and Protocol ("IPv4")
88              * Neutron defines the direction "ingress" as the vSwitch to the VM as defined in:
89              * http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html
90              *
91              */
92
93             if (portSecurityRule == null ||
94                     portSecurityRule.getSecurityRuleEthertype() == null ||
95                     portSecurityRule.getSecurityRuleDirection() == null) {
96                 continue;
97             }
98
99             if ("IPv4".equals(portSecurityRule.getSecurityRuleEthertype())
100                     && "ingress".equals(portSecurityRule.getSecurityRuleDirection())) {
101                 LOG.debug("programPortSecurityGroup: Rule matching IPv4 and ingress is: {} ", portSecurityRule);
102                 if (null != portSecurityRule.getSecurityRemoteGroupID()) {
103                     //Remote Security group is selected
104                     List<Neutron_IPs> remoteSrcAddressList = securityServicesManager
105                             .getVmListForSecurityGroup(portUuid,portSecurityRule.getSecurityRemoteGroupID());
106                     if (null != remoteSrcAddressList) {
107                         for (Neutron_IPs vmIp :remoteSrcAddressList ) {
108                             programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
109                                                     portSecurityRule, vmIp, write);
110                         }
111                         if (write) {
112                             securityGroupCacheManger.addToCache(portSecurityRule.getSecurityRemoteGroupID(), portUuid);
113                         } else {
114                             securityGroupCacheManger.removeFromCache(portSecurityRule.getSecurityRemoteGroupID(),
115                                                                      portUuid);
116                         }
117                     }
118                 } else {
119                     programPortSecurityRule(dpid, segmentationId, attachedMac, localPort,
120                                             portSecurityRule, null, write);
121                 }
122                 if (write) {
123                     securityGroupCacheManger.portAdded(securityGroup.getSecurityGroupUUID(), portUuid);
124                 } else {
125                     securityGroupCacheManger.portRemoved(securityGroup.getSecurityGroupUUID(), portUuid);
126                 }
127             }
128         }
129     }
130
131     @Override
132     public void programPortSecurityRule(Long dpid, String segmentationId, String attachedMac,
133                                         long localPort, NeutronSecurityRule portSecurityRule,
134                                         Neutron_IPs vmIp, boolean write) {
135         if (null == portSecurityRule.getSecurityRuleProtocol()) {
136             ingressAclIPv4(dpid, segmentationId, attachedMac,
137                            write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
138         } else {
139             String ipaddress = null;
140             if (null != vmIp) {
141                 ipaddress = vmIp.getIpAddress();
142                 try {
143                     InetAddress address = InetAddress.getByName(ipaddress);
144                     // TODO: remove this when ipv6 support is implemented
145                     if (address instanceof Inet6Address) {
146                         LOG.debug("Skipping ip address {}. IPv6 support is not yet implemented.", address);
147                         return;
148                     }
149                 } catch (UnknownHostException e) {
150                     LOG.warn("Invalid ip address {}", ipaddress, e);
151                     return;
152                 }
153             }
154
155             if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
156                 String ipPrefixStr = portSecurityRule.getSecurityRuleRemoteIpPrefix();
157                 try {
158                     IpPrefix ipPrefix = IpPrefixBuilder.getDefaultInstance(ipPrefixStr);
159                     // TODO: remove this when ipv6 support is implemented
160                     if (ipPrefix.getIpv6Prefix() != null) {
161                         LOG.debug("Skipping ip prefix {}. IPv6 support is not yet implemented.", ipPrefix);
162                         return;
163                     }
164                 } catch (IllegalArgumentException e) {
165                     LOG.warn("Invalid ip prefix {}", ipPrefixStr, e);
166                     return;
167                 }
168             }
169
170             switch (portSecurityRule.getSecurityRuleProtocol()) {
171               case MatchUtils.TCP:
172                   LOG.debug("programPortSecurityRule: Rule matching TCP", portSecurityRule);
173                   ingressAclTcp(dpid, segmentationId, attachedMac, portSecurityRule, ipaddress,
174                               write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
175                   break;
176               case MatchUtils.UDP:
177                   LOG.debug("programPortSecurityRule: Rule matching UDP", portSecurityRule);
178                   ingressAclUdp(dpid, segmentationId, attachedMac, portSecurityRule, ipaddress,
179                                 write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
180                   break;
181               case MatchUtils.ICMP:
182                   LOG.debug("programPortSecurityRule: Rule matching ICMP", portSecurityRule);
183                   ingressAclIcmp(dpid, segmentationId, attachedMac, portSecurityRule, ipaddress,
184                                  write, 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                   ingressOtherProtocolAclHandler(dpid, segmentationId, attachedMac, portSecurityRule,
190                               null, write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
191                   break;
192             }
193         }
194     }
195
196     private void ingressOtherProtocolAclHandler(Long dpidLong, String segmentationId, String dstMac,
197           NeutronSecurityRule portSecurityRule, String srcAddress,
198           boolean write, Integer protoPortMatchPriority) {
199
200           MatchBuilder matchBuilder = new MatchBuilder();
201           String flowId = "Ingress_Other_" + segmentationId + "_" + dstMac + "_";
202           matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
203           short proto = 0;
204           try {
205               Integer protocol = new Integer(portSecurityRule.getSecurityRuleProtocol());
206               proto = protocol.shortValue();
207               flowId = flowId + proto;
208           } catch (NumberFormatException e) {
209               LOG.error("Protocol vlaue conversion failure", e);
210           }
211           matchBuilder = MatchUtils.createIpProtocolMatch(matchBuilder, proto);
212           if (null != srcAddress) {
213               flowId = flowId + srcAddress;
214               matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
215                                         MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null);
216           } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
217               flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
218               matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
219                                         new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()),null);
220           }
221           String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
222           NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
223           flowId = flowId + "_Permit";
224           syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
225     }
226
227     @Override
228     public void programFixedSecurityGroup(Long dpid, String segmentationId, String dhcpMacAddress,
229                                         long localPort, boolean isLastPortinSubnet,
230                                         boolean isComputePort, boolean write) {
231         //If this port is the only port in the compute node add the DHCP server rule.
232         if (isLastPortinSubnet && isComputePort ) {
233             ingressAclDhcpAllowServerTraffic(dpid, segmentationId,dhcpMacAddress,
234                                              write,Constants.PROTO_DHCP_SERVER_MATCH_PRIORITY);
235         }
236     }
237
238     /**
239      * Allows IPv4 packet ingress to the destination mac address.
240      * @param dpidLong the dpid
241      * @param segmentationId the segementation id
242      * @param dstMac the destination mac address
243      * @param write add or remove
244      * @param protoPortMatchPriority the protocol match priority.
245      */
246     private void ingressAclIPv4(Long dpidLong, String segmentationId, String dstMac,
247                                 boolean write, Integer protoPortMatchPriority ) {
248         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
249         MatchBuilder matchBuilder = new MatchBuilder();
250         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
251         String flowId = "Ingress_IP" + segmentationId + "_" + dstMac + "_Permit_";
252         matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
253         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
254
255     }
256     /**
257      * Creates a ingress match to the dst macaddress. If src address is specified
258      * source specific match will be created. Otherwise a match with a CIDR will
259      * be created.
260      * @param dpidLong the dpid
261      * @param segmentationId the segmentation id
262      * @param dstMac the destination mac address.
263      * @param portSecurityRule the security rule in the SG
264      * @param srcAddress the destination IP address
265      * @param write add or delete
266      * @param protoPortMatchPriority the protocol match priroty
267      */
268     private void ingressAclTcp(Long dpidLong, String segmentationId, String dstMac,
269                                NeutronSecurityRule portSecurityRule, String srcAddress, boolean write,
270                                Integer protoPortMatchPriority ) {
271
272         MatchBuilder matchBuilder = new MatchBuilder();
273         FlowBuilder flowBuilder = new FlowBuilder();
274         String flowId = "Ingress_TCP_" + segmentationId + "_" + dstMac + "_";
275         matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
276
277         /* Custom TCP Match*/
278         if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
279             flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
280             matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0,
281                                                      portSecurityRule.getSecurityRulePortMin());
282         } else {
283             /* All TCP Match */
284             if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
285                     && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
286                 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
287                     + portSecurityRule.getSecurityRulePortMax() + "_";
288                 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0, 0);
289             }
290             /*TODO TCP PortRange Match*/
291
292         }
293
294         if (null != srcAddress) {
295             flowId = flowId + srcAddress;
296             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
297                                                         MatchUtils.iPv4PrefixFromIPv4Address(srcAddress),null);
298
299         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
300             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
301             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
302                                                         new Ipv4Prefix(portSecurityRule
303                                                                        .getSecurityRuleRemoteIpPrefix()),null);
304         }
305         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
306         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
307         flowId = flowId + "_Permit";
308         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
309
310     }
311
312     /**
313      * Creates a ingress match to the dst macaddress. If src address is specified
314      * source specific match will be created. Otherwise a match with a CIDR will
315      * be created.
316      * @param dpidLong the dpid
317      * @param segmentationId the segmentation id
318      * @param dstMac the destination mac address.
319      * @param portSecurityRule the security rule in the SG
320      * @param srcAddress the destination IP address
321      * @param write add or delete
322      * @param protoPortMatchPriority the protocol match priroty
323      */
324     private void ingressAclUdp(Long dpidLong, String segmentationId, String dstMac,
325                                NeutronSecurityRule portSecurityRule, String srcAddress,
326                                boolean write, Integer protoPortMatchPriority ) {
327         MatchBuilder matchBuilder = new MatchBuilder();
328         String flowId = "Ingress_UDP_" + segmentationId + "_" + dstMac + "_";
329         matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
330
331         /* Custom UDP Match */
332         if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
333             flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_";
334             matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0,
335                                                      portSecurityRule.getSecurityRulePortMin());
336         } else {
337             /* All UDP Match */
338             if (portSecurityRule.getSecurityRulePortMin().equals(PORT_RANGE_MIN)
339                     && portSecurityRule.getSecurityRulePortMax().equals(PORT_RANGE_MAX)) {
340                 flowId = flowId + portSecurityRule.getSecurityRulePortMin() + "_"
341                     + portSecurityRule.getSecurityRulePortMax() + "_";
342                 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0, 0);
343             }
344             /*TODO TCP PortRange Match*/
345
346         }
347
348         if (null != srcAddress) {
349             flowId = flowId + srcAddress;
350             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
351                                                         MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null);
352
353         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
354             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
355             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
356                                                         new Ipv4Prefix(portSecurityRule
357                                                                        .getSecurityRuleRemoteIpPrefix()),null);
358         }
359         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
360         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
361         flowId = flowId + "_Permit";
362         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
363
364     }
365
366     /**
367      * Creates a ingress match to the dst macaddress. If src address is specified
368      * source specific match will be created. Otherwise a match with a CIDR will
369      * be created.
370      * @param dpidLong the dpid
371      * @param segmentationId the segmentation id
372      * @param dstMac the destination mac address.
373      * @param portSecurityRule the security rule in the SG
374      * @param srcAddress the destination IP address
375      * @param write add or delete
376      * @param protoPortMatchPriority the protocol match priority
377      */
378     private void ingressAclIcmp(Long dpidLong, String segmentationId, String dstMac,
379                                 NeutronSecurityRule portSecurityRule, String srcAddress,
380                                 boolean write, Integer protoPortMatchPriority) {
381
382         MatchBuilder matchBuilder = new MatchBuilder();
383         String flowId = "Ingress_ICMP_" + segmentationId + "_" + dstMac + "_";
384         matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac);
385
386         /* Custom ICMP Match */
387         if (portSecurityRule.getSecurityRulePortMin() != null &&
388                 portSecurityRule.getSecurityRulePortMax() != null) {
389             flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
390                     + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
391             matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,
392                     portSecurityRule.getSecurityRulePortMin().shortValue(),
393                     portSecurityRule.getSecurityRulePortMax().shortValue());
394         } else {
395             /* All ICMP Match */
396             flowId = flowId + "all" + "_";
397             matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP);
398         }
399         if (null != srcAddress) {
400             flowId = flowId + srcAddress;
401             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
402                                                         MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null);
403         } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
404             flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
405             matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,
406                                                         new Ipv4Prefix(portSecurityRule
407                                                                        .getSecurityRuleRemoteIpPrefix()),null);
408         }
409         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
410         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
411         flowId = flowId + "_Permit";
412         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
413     }
414
415
416     public void ingressACLTcpSyn(Long dpidLong, String segmentationId, String attachedMac, boolean write,
417                                  Integer securityRulePortMin, Integer protoPortMatchPriority) {
418
419         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
420         PortNumber tcpPort = new PortNumber(securityRulePortMin);
421         MatchBuilder matchBuilder = new MatchBuilder();
422         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
423         FlowBuilder flowBuilder = new FlowBuilder();
424
425         flowBuilder.setMatch(MatchUtils.createDmacTcpSynMatch(matchBuilder, attachedMac, tcpPort,
426                                                               Constants.TCP_SYN, segmentationId).build());
427
428         LOG.debug("ingressACLTcpSyn MatchBuilder contains:  {}", flowBuilder.getMatch());
429         String flowId = "UcastOut_ACL2_" + segmentationId + "_" + attachedMac + securityRulePortMin;
430         // Add Flow Attributes
431         flowBuilder.setId(new FlowId(flowId));
432         FlowKey key = new FlowKey(new FlowId(flowId));
433         flowBuilder.setStrict(false);
434         flowBuilder.setPriority(protoPortMatchPriority);
435         flowBuilder.setBarrier(true);
436         flowBuilder.setTableId(this.getTable());
437         flowBuilder.setKey(key);
438         flowBuilder.setFlowName(flowId);
439         flowBuilder.setHardTimeout(0);
440         flowBuilder.setIdleTimeout(0);
441
442         if (write) {
443             // Instantiate the Builders for the OF Actions and Instructions
444             InstructionsBuilder isb = new InstructionsBuilder();
445             List<Instruction> instructionsList = Lists.newArrayList();
446
447             InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
448             ib.setOrder(0);
449             ib.setKey(new InstructionKey(0));
450             instructionsList.add(ib.build());
451             isb.setInstruction(instructionsList);
452
453             LOG.debug("Instructions are: {}", ib.getInstruction());
454             // Add InstructionsBuilder to FlowBuilder
455             flowBuilder.setInstructions(isb.build());
456             writeFlow(flowBuilder, nodeBuilder);
457         } else {
458             removeFlow(flowBuilder, nodeBuilder);
459         }
460     }
461
462     public void ingressACLTcpPortWithPrefix(Long dpidLong, String segmentationId, String attachedMac,
463                                             boolean write, Integer securityRulePortMin, String securityRuleIpPrefix,
464                                             Integer protoPortPrefixMatchPriority) {
465
466         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
467         PortNumber tcpPort = new PortNumber(securityRulePortMin);
468
469         MatchBuilder matchBuilder = new MatchBuilder();
470         NodeBuilder nodeBuilder = this.createNodeBuilder(nodeName);
471         FlowBuilder flowBuilder = new FlowBuilder();
472         Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
473
474         flowBuilder.setMatch(MatchUtils
475                              .createDmacTcpSynDstIpPrefixTcpPort(matchBuilder, new MacAddress(attachedMac),
476                                                                  tcpPort, Constants.TCP_SYN, segmentationId, srcIpPrefix).build());
477
478         LOG.debug(" MatchBuilder contains:  {}", flowBuilder.getMatch());
479         String flowId = "UcastOut2_" + segmentationId + "_" + attachedMac +
480                 securityRulePortMin + securityRuleIpPrefix;
481         // Add Flow Attributes
482         flowBuilder.setId(new FlowId(flowId));
483         FlowKey key = new FlowKey(new FlowId(flowId));
484         flowBuilder.setStrict(false);
485         flowBuilder.setPriority(protoPortPrefixMatchPriority);
486         flowBuilder.setBarrier(true);
487         flowBuilder.setTableId(this.getTable());
488         flowBuilder.setKey(key);
489         flowBuilder.setFlowName(flowId);
490         flowBuilder.setHardTimeout(0);
491         flowBuilder.setIdleTimeout(0);
492
493         if (write) {
494             // Instantiate the Builders for the OF Actions and Instructions
495             InstructionsBuilder isb = new InstructionsBuilder();
496
497             List<Instruction> instructionsList = Lists.newArrayList();
498             InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
499             ib.setOrder(0);
500             ib.setKey(new InstructionKey(0));
501             instructionsList.add(ib.build());
502             isb.setInstruction(instructionsList);
503
504             LOG.debug("Instructions contain: {}", ib.getInstruction());
505             // Add InstructionsBuilder to FlowBuilder
506             flowBuilder.setInstructions(isb.build());
507             writeFlow(flowBuilder, nodeBuilder);
508         } else {
509             removeFlow(flowBuilder, nodeBuilder);
510         }
511     }
512
513     public void handleIngressAllowProto(Long dpidLong, String segmentationId, String attachedMac, boolean write,
514                                         String securityRuleProtcol, Integer protoMatchPriority) {
515
516         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
517
518         MatchBuilder matchBuilder = new MatchBuilder();
519         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
520         FlowBuilder flowBuilder = new FlowBuilder();
521
522         flowBuilder.setMatch(MatchUtils
523                              .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null).build());
524         flowBuilder.setMatch(MatchUtils
525                              .createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
526         LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
527
528         String flowId = "UcastOut_" + segmentationId + "_" +
529                 attachedMac + "_AllowTCPSynPrefix_" + securityRuleProtcol;
530         // Add Flow Attributes
531         flowBuilder.setId(new FlowId(flowId));
532         FlowKey key = new FlowKey(new FlowId(flowId));
533         flowBuilder.setStrict(false);
534         flowBuilder.setPriority(protoMatchPriority);
535         flowBuilder.setBarrier(true);
536         flowBuilder.setTableId(this.getTable());
537         flowBuilder.setKey(key);
538         flowBuilder.setFlowName(flowId);
539         flowBuilder.setHardTimeout(0);
540         flowBuilder.setIdleTimeout(0);
541
542         if (write) {
543             // Instantiate the Builders for the OF Actions and Instructions
544             InstructionsBuilder isb = new InstructionsBuilder();
545             List<Instruction> instructionsList = Lists.newArrayList();
546
547             InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
548             ib.setOrder(1);
549             ib.setKey(new InstructionKey(1));
550             instructionsList.add(ib.build());
551             isb.setInstruction(instructionsList);
552             LOG.debug("Instructions contain: {}", ib.getInstruction());
553
554             // Add InstructionsBuilder to FlowBuilder
555             flowBuilder.setInstructions(isb.build());
556             writeFlow(flowBuilder, nodeBuilder);
557         } else {
558             removeFlow(flowBuilder, nodeBuilder);
559         }
560     }
561
562
563     public void ingressACLDefaultTcpDrop(Long dpidLong, String segmentationId, String attachedMac,
564                                          int priority, boolean write) {
565
566         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
567         MatchBuilder matchBuilder = new MatchBuilder();
568         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
569         FlowBuilder flowBuilder = new FlowBuilder();
570
571         flowBuilder.setMatch(MatchUtils.createDmacTcpPortWithFlagMatch(matchBuilder,
572                                                                        attachedMac, Constants.TCP_SYN, segmentationId).build());
573
574         LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
575         String flowId = "PortSec_TCP_Syn_Default_Drop_" + segmentationId + "_" + attachedMac;
576         flowBuilder.setId(new FlowId(flowId));
577         FlowKey key = new FlowKey(new FlowId(flowId));
578         flowBuilder.setStrict(false);
579         flowBuilder.setPriority(priority);
580         flowBuilder.setBarrier(true);
581         flowBuilder.setTableId(this.getTable());
582         flowBuilder.setKey(key);
583         flowBuilder.setFlowName(flowId);
584         flowBuilder.setHardTimeout(0);
585         flowBuilder.setIdleTimeout(0);
586
587         if (write) {
588             // Instantiate the Builders for the OF Actions and Instructions
589             InstructionBuilder ib = new InstructionBuilder();
590             InstructionsBuilder isb = new InstructionsBuilder();
591
592             // Instructions List Stores Individual Instructions
593             List<Instruction> instructions = Lists.newArrayList();
594
595             // Set the Output Port/Iface
596             InstructionUtils.createDropInstructions(ib);
597             ib.setOrder(0);
598             ib.setKey(new InstructionKey(0));
599             instructions.add(ib.build());
600
601             // Add InstructionBuilder to the Instruction(s)Builder List
602             isb.setInstruction(instructions);
603             LOG.debug("Instructions contain: {}", ib.getInstruction());
604             // Add InstructionsBuilder to FlowBuilder
605             flowBuilder.setInstructions(isb.build());
606             writeFlow(flowBuilder, nodeBuilder);
607         } else {
608             removeFlow(flowBuilder, nodeBuilder);
609         }
610     }
611
612     public void ingressACLPermitAllProto(Long dpidLong, String segmentationId, String attachedMac,
613                                          boolean write, String securityRuleIpPrefix, Integer protoPortMatchPriority) {
614         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
615         Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
616         MatchBuilder matchBuilder = new MatchBuilder();
617         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
618         FlowBuilder flowBuilder = new FlowBuilder();
619
620         flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId))
621                              .build());
622         if (securityRuleIpPrefix != null) {
623             flowBuilder.setMatch(MatchUtils
624                                  .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, srcIpPrefix)
625                                  .build());
626         } else {
627             flowBuilder.setMatch(MatchUtils
628                                  .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null)
629                                  .build());
630         }
631
632         LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
633         String flowId = "IngressProto_ACL_" + segmentationId + "_" +
634                 attachedMac + "_Permit_" + securityRuleIpPrefix;
635         // Add Flow Attributes
636         flowBuilder.setId(new FlowId(flowId));
637         FlowKey key = new FlowKey(new FlowId(flowId));
638         flowBuilder.setStrict(false);
639         flowBuilder.setPriority(protoPortMatchPriority);
640         flowBuilder.setBarrier(true);
641         flowBuilder.setTableId(this.getTable());
642         flowBuilder.setKey(key);
643         flowBuilder.setFlowName(flowId);
644         flowBuilder.setHardTimeout(0);
645         flowBuilder.setIdleTimeout(0);
646
647         if (write) {
648             // Instantiate the Builders for the OF Actions and Instructions
649             InstructionBuilder ib = new InstructionBuilder();
650             InstructionsBuilder isb = new InstructionsBuilder();
651             List<Instruction> instructionsList = Lists.newArrayList();
652
653             ib = this.getMutablePipelineInstructionBuilder();
654             ib.setOrder(1);
655             ib.setKey(new InstructionKey(0));
656             instructionsList.add(ib.build());
657             isb.setInstruction(instructionsList);
658
659             LOG.debug("Instructions contain: {}", ib.getInstruction());
660             // Add InstructionsBuilder to FlowBuilder
661             flowBuilder.setInstructions(isb.build());
662             writeFlow(flowBuilder, nodeBuilder);
663         } else {
664             removeFlow(flowBuilder, nodeBuilder);
665         }
666     }
667
668     /**
669      * Add rule to ensure only DHCP server traffic from the specified mac is allowed.
670      *
671      * @param dpidLong the dpid
672      * @param segmentationId the segmentation id
673      * @param dhcpMacAddress the DHCP server mac address
674      * @param write is write or delete
675      * @param protoPortMatchPriority the priority
676      */
677     private void ingressAclDhcpAllowServerTraffic(Long dpidLong, String segmentationId, String dhcpMacAddress,
678                                                   boolean write, Integer protoPortMatchPriority) {
679
680         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
681         MatchBuilder matchBuilder = new MatchBuilder();
682         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
683         MatchUtils.createDhcpServerMatch(matchBuilder, dhcpMacAddress, 67, 68).build();
684         LOG.debug("ingressAclDHCPAllowServerTraffic: MatchBuilder contains: {}", matchBuilder);
685         String flowId = "Ingress_DHCP_Server" + segmentationId + "_" + dhcpMacAddress + "_Permit_";
686         syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
687     }
688
689     /**
690      * Add or remove flow to the node.
691      *
692      * @param flowId the the flow id
693      * @param nodeBuilder the node builder
694      * @param matchBuilder the matchbuilder
695      * @param protoPortMatchPriority the protocol priority
696      * @param write whether it is a write
697      * @param drop whether it is a drop or forward
698      */
699     private void syncFlow(String flowId, NodeBuilder nodeBuilder,
700                           MatchBuilder matchBuilder,Integer protoPortMatchPriority,
701                           boolean write,boolean drop) {
702         FlowBuilder flowBuilder = new FlowBuilder();
703         flowBuilder.setMatch(matchBuilder.build());
704         flowBuilder.setId(new FlowId(flowId));
705         FlowKey key = new FlowKey(new FlowId(flowId));
706         flowBuilder.setStrict(false);
707         flowBuilder.setPriority(protoPortMatchPriority);
708         flowBuilder.setBarrier(true);
709         flowBuilder.setTableId(this.getTable());
710         flowBuilder.setKey(key);
711         flowBuilder.setFlowName(flowId);
712         flowBuilder.setHardTimeout(0);
713         flowBuilder.setIdleTimeout(0);
714
715         if (write) {
716             // Instantiate the Builders for the OF Actions and Instructions
717             InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
718             if (drop) {
719                 InstructionUtils.createDropInstructions(ib);
720             }
721             ib.setOrder(0);
722             InstructionsBuilder isb = new InstructionsBuilder();
723             List<Instruction> instructionsList = Lists.newArrayList();
724             ib.setKey(new InstructionKey(0));
725             instructionsList.add(ib.build());
726             isb.setInstruction(instructionsList);
727             flowBuilder.setInstructions(isb.build());
728             writeFlow(flowBuilder, nodeBuilder);
729         } else {
730             removeFlow(flowBuilder, nodeBuilder);
731         }
732
733     }
734
735     @Override
736     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
737         super.setDependencies(bundleContext.getServiceReference(IngressAclProvider.class.getName()), this);
738         securityServicesManager =
739                 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
740         securityGroupCacheManger =
741                 (SecurityGroupCacheManger) ServiceHelper.getGlobalInstance(SecurityGroupCacheManger.class, this);
742     }
743
744     @Override
745     public void setDependencies(Object impl) {
746
747     }
748 }