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