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