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