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