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