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