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