Clean up logging
[ovsdb.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / providers / openflow13 / services / EgressAclService.java
1 /*
2  * Copyright (C) 2014 Red Hat, Inc.
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  * Authors : Madhu Venugopal
9  */
10 package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services;
11
12 import java.math.BigInteger;
13 import java.net.InetAddress;
14 import java.util.Iterator;
15 import java.util.List;
16
17 import org.opendaylight.neutron.spi.NeutronSecurityGroup;
18 import org.opendaylight.neutron.spi.NeutronSecurityRule;
19 import org.opendaylight.neutron.spi.Neutron_IPs;
20 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
21 import org.opendaylight.ovsdb.openstack.netvirt.api.EgressAclProvider;
22 import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
23 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
24 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
25 import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
26 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
39 import org.osgi.framework.BundleContext;
40 import org.osgi.framework.ServiceReference;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 import com.google.common.collect.Lists;
45
46 public class EgressAclService extends AbstractServiceInstance implements EgressAclProvider, ConfigInterface {
47
48     private static final Logger LOG = LoggerFactory.getLogger(EgressAclService.class);
49     final int DHCP_SOURCE_PORT = 67;
50     final int DHCP_DESTINATION_PORT = 68;
51     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
65         LOG.trace("programLocalBridgeRulesWithSec neutronSecurityGroup: {} ", securityGroup);
66         List<NeutronSecurityRule> portSecurityList = securityGroup.getSecurityRules();
67         /* Iterate over the Port Security Rules in the Port Security Group bound to the port*/
68         for (NeutronSecurityRule portSecurityRule : portSecurityList) {
69             /**
70              * Neutron Port Security ACL "egress" and "IPv4"
71              *
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().equalsIgnoreCase("IPv4") &&
79                 portSecurityRule.getSecurityRuleDirection().equalsIgnoreCase("egress")) {
80                 LOG.debug("Egress IPV4 ACL  Port Security Rule: {} ", portSecurityRule);
81                 // ToDo: Implement Port Range
82
83                 /**
84                  * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (True)
85                  */
86                 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
87                     !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
88                     !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
89                     (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
90                      !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
91                              .equalsIgnoreCase("0.0.0.0/0"))) {
92                     LOG.debug(
93                             "Rule #1 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
94                             portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
95                             portSecurityRule.getSecurityRulePortMax(),
96                             portSecurityRule.getSecurityRuleRemoteIpPrefix());
97                     egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
98                                             Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP,
99                                             true);
100                     egressACLTcpPortWithPrefix(dpid, segmentationId,
101                                                attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
102                                                portSecurityRule.getSecurityRuleRemoteIpPrefix(),
103                                                Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
104                     continue;
105                 }
106                 /**
107                  * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (True)
108                  */
109                 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
110                     !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
111                     String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
112                     (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
113                      !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
114                              .equalsIgnoreCase("0.0.0.0/0"))) {
115                     LOG.debug(
116                             "Rule #2 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
117                             portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
118                             portSecurityRule.getSecurityRulePortMax(),
119                             portSecurityRule.getSecurityRuleRemoteIpPrefix());
120                     egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
121                                             Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP,
122                                             true);
123                     egressACLTcpPortWithPrefix(dpid, segmentationId,
124                                                attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
125                                                portSecurityRule.getSecurityRuleRemoteIpPrefix(),
126                                                Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
127                     continue;
128                 }
129                 /**
130                  * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True)
131                  */
132                 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
133                     String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
134                     String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
135                     !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
136                     LOG.debug(
137                             "Rule #3 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
138                             portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
139                             portSecurityRule.getSecurityRulePortMax(),
140                             portSecurityRule.getSecurityRuleRemoteIpPrefix());
141                     egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PROTO_PREFIX_MATCH_PRIORITY_DROP,
142                                             true);
143                     egressACLPermitAllProto(dpid, segmentationId, attachedMac, true,
144                                             portSecurityRule.getSecurityRuleRemoteIpPrefix(), Constants.PROTO_PREFIX_MATCH_PRIORITY);
145                     continue;
146                 }
147                 /**
148                  * TCP Proto (False), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True)
149                  */
150                 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("null") &&
151                     String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
152                     String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
153                     (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
154                      !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
155                              .equalsIgnoreCase("0.0.0.0/0"))) {
156                     LOG.debug(
157                             "Rule #4 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
158                             portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
159                             portSecurityRule.getSecurityRulePortMax(),
160                             portSecurityRule.getSecurityRuleRemoteIpPrefix());
161                     egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PREFIX_MATCH_PRIORITY_DROP, true);
162                     egressACLPermitAllProto(dpid, segmentationId, attachedMac, true,
163                                             portSecurityRule.getSecurityRuleRemoteIpPrefix(), Constants.PREFIX_MATCH_PRIORITY);
164                     continue;
165                 }
166                 /**
167                  * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (False)
168                  */
169                 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
170                     !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
171                     !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
172                     String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
173                     LOG.debug(
174                             "Rule #5 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
175                             portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
176                             portSecurityRule.getSecurityRulePortMax(),
177                             portSecurityRule.getSecurityRuleRemoteIpPrefix());
178                     egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PROTO_PORT_MATCH_PRIORITY_DROP,
179                                             true);
180                     egressACLTcpSyn(dpid, segmentationId,
181                                     attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
182                                     Constants.PROTO_PORT_MATCH_PRIORITY);
183                     continue;
184                 }
185                 /**
186                  * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (False)
187                  */
188                 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
189                     !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
190                     String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
191                     String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
192                     LOG.debug(
193                             "Rule #6 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
194                             portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
195                             portSecurityRule.getSecurityRulePortMax(),
196                             portSecurityRule.getSecurityRuleRemoteIpPrefix());
197                     egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
198                                             Constants.PROTO_PORT_MATCH_PRIORITY_DROP, true);
199                     egressACLTcpSyn(dpid, segmentationId, attachedMac, true,
200                                     portSecurityRule.getSecurityRulePortMin(), Constants.PROTO_PORT_MATCH_PRIORITY);
201                     continue;
202                 }
203                 /**
204                  * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (False or 0.0.0.0/0)
205                  */
206                 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
207                     String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
208                     String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
209                     ((String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) ||
210                      String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
211                              .equalsIgnoreCase("0.0.0.0/0"))) {
212                     LOG.debug(
213                             "Rule #7 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
214                             portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
215                             portSecurityRule.getSecurityRulePortMax(),
216                             portSecurityRule.getSecurityRuleRemoteIpPrefix());
217                     // No need to drop until UDP/ICMP are implemented
218                     // egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, PROTO_MATCH_PRIORITY_DROP, true);
219                     egressAllowProto(dpid, segmentationId, attachedMac, true,
220                                      portSecurityRule.getSecurityRuleProtocol(), Constants.PROTO_MATCH_PRIORITY);
221                     continue;
222                 }
223                 LOG.debug("ACL Match combination not found for rule: {}", portSecurityRule);
224             }
225         }
226     }
227
228     @Override
229     public void programFixedSecurityACL(Long dpid, String segmentationId, String attachedMac,
230             long localPort, List<Neutron_IPs> srcAddressList, boolean isLastPortinBridge, boolean isComputePort ,boolean write) {
231         // If it is the only port in the bridge add the rule to allow any DHCP client traffic
232         if (isLastPortinBridge) {
233             egressACLDHCPAllowClientTrafficFromVm(dpid, write, Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY);
234         }
235         if(isComputePort) {
236         // add rule to drop the DHCP server traffic originating from the vm.
237             egressACLDHCPDropServerTrafficfromVM(dpid, localPort, write, Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
238             //Adds rule to check legitimate ip/mac pair for each packet from the vm
239             for(Neutron_IPs srcAddress : srcAddressList) {
240                 String addressWithPrefix = srcAddress.getIpAddress() + HOST_MASK;
241                 egressACLAllowTrafficFromVmIpMacPair(dpid, localPort, attachedMac, addressWithPrefix, Constants.PROTO_VM_IP_MAC_MATCH_PRIORITY,write);
242             }
243         }
244     }
245
246     public void egressACLDefaultTcpDrop(Long dpidLong, String segmentationId, String attachedMac,
247                                         int priority, boolean write) {
248
249         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
250         MatchBuilder matchBuilder = new MatchBuilder();
251         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
252         FlowBuilder flowBuilder = new FlowBuilder();
253
254         flowBuilder.setMatch(MatchUtils.createSmacTcpPortWithFlagMatch(matchBuilder,
255                                                                        attachedMac, Constants.TCP_SYN, segmentationId).build());
256         LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
257
258         String flowId = "TCP_Syn_Egress_Default_Drop_" + segmentationId + "_" + attachedMac;
259         flowBuilder.setId(new FlowId(flowId));
260         FlowKey key = new FlowKey(new FlowId(flowId));
261         flowBuilder.setStrict(false);
262         flowBuilder.setPriority(priority);
263         flowBuilder.setBarrier(true);
264         flowBuilder.setTableId(this.getTable());
265         flowBuilder.setKey(key);
266         flowBuilder.setFlowName(flowId);
267         flowBuilder.setHardTimeout(0);
268         flowBuilder.setIdleTimeout(0);
269
270         if (write) {
271             // Instantiate the Builders for the OF Actions and Instructions
272             InstructionBuilder ib = new InstructionBuilder();
273             InstructionsBuilder isb = new InstructionsBuilder();
274             List<Instruction> instructions = Lists.newArrayList();
275
276             InstructionUtils.createDropInstructions(ib);
277             ib.setOrder(0);
278             ib.setKey(new InstructionKey(0));
279             instructions.add(ib.build());
280             // Add InstructionBuilder to the Instruction(s)Builder List
281             isb.setInstruction(instructions);
282
283             LOG.debug("Instructions contain: {}", ib.getInstruction());
284             // Add InstructionsBuilder to FlowBuilder
285             flowBuilder.setInstructions(isb.build());
286             writeFlow(flowBuilder, nodeBuilder);
287         } else {
288             removeFlow(flowBuilder, nodeBuilder);
289         }
290     }
291
292     public void egressACLTcpPortWithPrefix(Long dpidLong, String segmentationId, String attachedMac, boolean write,
293                                            Integer securityRulePortMin, String securityRuleIpPrefix, Integer protoPortPrefixMatchPriority) {
294
295         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
296         PortNumber tcpPort = new PortNumber(securityRulePortMin);
297         MatchBuilder matchBuilder = new MatchBuilder();
298         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
299         FlowBuilder flowBuilder = new FlowBuilder();
300         Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
301
302         flowBuilder.setMatch(MatchUtils
303                                      .createSmacTcpSynDstIpPrefixTcpPort(matchBuilder, new MacAddress(attachedMac),
304                                                                          tcpPort, Constants.TCP_SYN, segmentationId, srcIpPrefix).build());
305
306         LOG.debug(" MatchBuilder contains:  {}", flowBuilder.getMatch());
307         String flowId = "UcastEgress_" + segmentationId + "_" + attachedMac +
308                         securityRulePortMin + securityRuleIpPrefix;
309         // Add Flow Attributes
310         flowBuilder.setId(new FlowId(flowId));
311         FlowKey key = new FlowKey(new FlowId(flowId));
312         flowBuilder.setStrict(false);
313         flowBuilder.setPriority(protoPortPrefixMatchPriority);
314         flowBuilder.setBarrier(true);
315         flowBuilder.setTableId(this.getTable());
316         flowBuilder.setKey(key);
317         flowBuilder.setFlowName(flowId);
318         flowBuilder.setHardTimeout(0);
319         flowBuilder.setIdleTimeout(0);
320
321         if (write) {
322             // Instantiate the Builders for the OF Actions and Instructions
323             InstructionBuilder ib = new InstructionBuilder();
324             InstructionsBuilder isb = new InstructionsBuilder();
325             List<Instruction> instructionsList = Lists.newArrayList();
326
327             ib = this.getMutablePipelineInstructionBuilder();
328             ib.setOrder(0);
329             ib.setKey(new InstructionKey(0));
330             instructionsList.add(ib.build());
331             isb.setInstruction(instructionsList);
332
333             LOG.debug("Instructions contain: {}", ib.getInstruction());
334             // Add InstructionsBuilder to FlowBuilder
335             flowBuilder.setInstructions(isb.build());
336             writeFlow(flowBuilder, nodeBuilder);
337         } else {
338             removeFlow(flowBuilder, nodeBuilder);
339         }
340     }
341
342
343
344     public void egressAllowProto(Long dpidLong, String segmentationId, String attachedMac, boolean write,
345                                  String securityRuleProtcol, Integer protoMatchPriority) {
346
347         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
348         MatchBuilder matchBuilder = new MatchBuilder();
349         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
350         FlowBuilder flowBuilder = new FlowBuilder();
351
352         flowBuilder.setMatch(MatchUtils
353                                      .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null).build());
354         flowBuilder.setMatch(MatchUtils
355                                      .createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
356
357         LOG.debug("MatchBuilder contains:  {}", flowBuilder.getMatch());
358         String flowId = "EgressAllProto_" + segmentationId + "_" +
359                         attachedMac + "_AllowEgressTCPSyn_" + securityRuleProtcol;
360         // Add Flow Attributes
361         flowBuilder.setId(new FlowId(flowId));
362         FlowKey key = new FlowKey(new FlowId(flowId));
363         flowBuilder.setStrict(false);
364         flowBuilder.setPriority(protoMatchPriority);
365         flowBuilder.setBarrier(true);
366         flowBuilder.setTableId(this.getTable());
367         flowBuilder.setKey(key);
368         flowBuilder.setFlowName(flowId);
369         flowBuilder.setHardTimeout(0);
370         flowBuilder.setIdleTimeout(0);
371
372         if (write) {
373             // Instantiate the Builders for the OF Actions and Instructions
374             InstructionBuilder ib = new InstructionBuilder();
375             InstructionsBuilder isb = new InstructionsBuilder();
376             List<Instruction> instructionsList = Lists.newArrayList();
377
378             ib = this.getMutablePipelineInstructionBuilder();
379             ib.setOrder(0);
380             ib.setKey(new InstructionKey(0));
381             instructionsList.add(ib.build());
382             isb.setInstruction(instructionsList);
383
384             LOG.debug("Instructions contain: {}", ib.getInstruction());
385             // Add InstructionsBuilder to FlowBuilder
386             flowBuilder.setInstructions(isb.build());
387             writeFlow(flowBuilder, nodeBuilder);
388         } else {
389             removeFlow(flowBuilder, nodeBuilder);
390         }
391     }
392
393     public void egressACLPermitAllProto(Long dpidLong, String segmentationId, String attachedMac,
394                                         boolean write, String securityRuleIpPrefix, Integer protoPortMatchPriority) {
395
396         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
397         Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
398         MatchBuilder matchBuilder = new MatchBuilder();
399         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
400         FlowBuilder flowBuilder = new FlowBuilder();
401
402         flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId))
403                                      .build());
404         if (securityRuleIpPrefix != null) {
405             flowBuilder.setMatch(MatchUtils
406                                          .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, srcIpPrefix)
407                                          .build());
408         } else {
409             flowBuilder.setMatch(MatchUtils
410                                          .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null)
411                                          .build());
412         }
413         LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
414         String flowId = "Egress_Proto_ACL" + segmentationId + "_" +
415                         attachedMac + "_Permit_" + securityRuleIpPrefix;
416         // Add Flow Attributes
417         flowBuilder.setId(new FlowId(flowId));
418         FlowKey key = new FlowKey(new FlowId(flowId));
419         flowBuilder.setStrict(false);
420         flowBuilder.setPriority(protoPortMatchPriority);
421         flowBuilder.setBarrier(true);
422         flowBuilder.setTableId(this.getTable());
423         flowBuilder.setKey(key);
424         flowBuilder.setFlowName(flowId);
425         flowBuilder.setHardTimeout(0);
426         flowBuilder.setIdleTimeout(0);
427
428         if (write) {
429             // Instantiate the Builders for the OF Actions and Instructions
430             InstructionBuilder ib = new InstructionBuilder();
431             InstructionsBuilder isb = new InstructionsBuilder();
432             List<Instruction> instructionsList = Lists.newArrayList();
433
434             ib = this.getMutablePipelineInstructionBuilder();
435             ib.setOrder(0);
436             ib.setKey(new InstructionKey(0));
437             instructionsList.add(ib.build());
438             isb.setInstruction(instructionsList);
439
440             LOG.debug("Instructions contain: {}", ib.getInstruction());
441             // Add InstructionsBuilder to FlowBuilder
442             flowBuilder.setInstructions(isb.build());
443             writeFlow(flowBuilder, nodeBuilder);
444         } else {
445             removeFlow(flowBuilder, nodeBuilder);
446         }
447     }
448
449
450     public void egressACLTcpSyn(Long dpidLong, String segmentationId, String attachedMac, boolean write,
451                                 Integer securityRulePortMin, Integer protoPortMatchPriority) {
452
453         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
454         PortNumber tcpPort = new PortNumber(securityRulePortMin);
455         MatchBuilder matchBuilder = new MatchBuilder();
456         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
457         FlowBuilder flowBuilder = new FlowBuilder();
458
459         flowBuilder.setMatch(MatchUtils.createSmacTcpSyn(matchBuilder, attachedMac, tcpPort,
460                                                          Constants.TCP_SYN, segmentationId).build());
461
462         LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
463         String flowId = "Ucast_this.getTable()" + segmentationId + "_" + attachedMac + securityRulePortMin;
464         // Add Flow Attributes
465         flowBuilder.setId(new FlowId(flowId));
466         FlowKey key = new FlowKey(new FlowId(flowId));
467         flowBuilder.setStrict(false);
468         flowBuilder.setPriority(protoPortMatchPriority);
469         flowBuilder.setBarrier(true);
470         flowBuilder.setTableId(this.getTable());
471         flowBuilder.setKey(key);
472         flowBuilder.setFlowName(flowId);
473         flowBuilder.setHardTimeout(0);
474         flowBuilder.setIdleTimeout(0);
475
476         if (write) {
477             // Instantiate the Builders for the OF Actions and Instructions
478             InstructionBuilder ib = new InstructionBuilder();
479             InstructionsBuilder isb = new InstructionsBuilder();
480             List<Instruction> instructionsList = Lists.newArrayList();
481
482             ib = this.getMutablePipelineInstructionBuilder();
483             ib.setOrder(0);
484             ib.setKey(new InstructionKey(0));
485             instructionsList.add(ib.build());
486             isb.setInstruction(instructionsList);
487
488             LOG.debug("Instructions contain: {}", ib.getInstruction());
489             // Add InstructionsBuilder to FlowBuilder
490             flowBuilder.setInstructions(isb.build());
491             writeFlow(flowBuilder, nodeBuilder);
492         } else {
493             removeFlow(flowBuilder, nodeBuilder);
494         }
495     }
496
497     /**
498      * Adds flow to allow any DHCP client traffic
499      *
500      * @param dpidLong the dpid
501      * @param write whether to write or delete the flow
502      * @param protoPortMatchPriority the priority
503      */
504     public void egressACLDHCPAllowClientTrafficFromVm(Long dpidLong,
505             boolean write, Integer protoPortMatchPriority) {
506
507         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
508         MatchBuilder matchBuilder = new MatchBuilder();
509         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
510         FlowBuilder flowBuilder = new FlowBuilder();
511
512         flowBuilder.setMatch(MatchUtils.createDHCPMatch(matchBuilder, DHCP_DESTINATION_PORT, DHCP_SOURCE_PORT).build());
513         LOG.debug("egressACLDHCPAllowClientTrafficFromVm: MatchBuilder contains: {}", flowBuilder.getMatch());
514         String flowId = "Egress_DHCP_Client"  + "_Permit_";
515         // Add Flow Attributes
516         flowBuilder.setId(new FlowId(flowId));
517         FlowKey key = new FlowKey(new FlowId(flowId));
518         flowBuilder.setStrict(false);
519         flowBuilder.setPriority(protoPortMatchPriority);
520         flowBuilder.setBarrier(true);
521         flowBuilder.setTableId(this.getTable());
522         flowBuilder.setKey(key);
523         flowBuilder.setFlowName(flowId);
524         flowBuilder.setHardTimeout(0);
525         flowBuilder.setIdleTimeout(0);
526
527         if (write) {
528             // Instantiate the Builders for the OF Actions and Instructions
529             InstructionBuilder ib = new InstructionBuilder();
530             InstructionsBuilder isb = new InstructionsBuilder();
531             List<Instruction> instructionsList = Lists.newArrayList();
532
533             ib = this.getMutablePipelineInstructionBuilder();
534             ib.setOrder(0);
535             ib.setKey(new InstructionKey(0));
536             instructionsList.add(ib.build());
537             isb.setInstruction(instructionsList);
538
539             LOG.debug("egressACLDHCPAllowClientTrafficFromVm: Instructions contain: {}", ib.getInstruction());
540             // Add InstructionsBuilder to FlowBuilder
541             flowBuilder.setInstructions(isb.build());
542             writeFlow(flowBuilder, nodeBuilder);
543         } else {
544             removeFlow(flowBuilder, nodeBuilder);
545         }
546     }
547
548     /**
549      * Adds rule to prevent DHCP spoofing by the vm attached to the port.
550      *
551      * @param dpidLong the dpid
552      * @param localPort the local port
553      * @param write is write or delete
554      * @param protoPortMatchPriority  the priority
555      */
556     public void egressACLDHCPDropServerTrafficfromVM(Long dpidLong, long localPort,
557             boolean write, Integer protoPortMatchPriority) {
558
559         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
560         MatchBuilder matchBuilder = new MatchBuilder();
561         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
562         FlowBuilder flowBuilder = new FlowBuilder();
563         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
564         flowBuilder.setMatch(MatchUtils.createDHCPMatch(matchBuilder, DHCP_SOURCE_PORT, DHCP_DESTINATION_PORT).build());
565
566         LOG.debug("egressACLDHCPDropServerTrafficfromVM: MatchBuilder contains: {}", flowBuilder.getMatch());
567         String flowId = "Egress_DHCP_Server" + "_" + localPort + "_DROP_";
568         // Add Flow Attributes
569         flowBuilder.setId(new FlowId(flowId));
570         FlowKey key = new FlowKey(new FlowId(flowId));
571         flowBuilder.setStrict(false);
572         flowBuilder.setPriority(protoPortMatchPriority);
573         flowBuilder.setBarrier(true);
574         flowBuilder.setTableId(this.getTable());
575         flowBuilder.setKey(key);
576         flowBuilder.setFlowName(flowId);
577         flowBuilder.setHardTimeout(0);
578         flowBuilder.setIdleTimeout(0);
579
580         if (write) {
581             // Instantiate the Builders for the OF Actions and Instructions
582             InstructionBuilder ib = new InstructionBuilder();
583             InstructionsBuilder isb = new InstructionsBuilder();
584             List<Instruction> instructionsList = Lists.newArrayList();
585
586             InstructionUtils.createDropInstructions(ib);
587             ib.setOrder(0);
588             ib.setKey(new InstructionKey(0));
589             instructionsList.add(ib.build());
590             isb.setInstruction(instructionsList);
591
592             LOG.debug("egressACLDHCPDropServerTrafficfromVM: Instructions contain: {}", ib.getInstruction());
593             // Add InstructionsBuilder to FlowBuilder
594             flowBuilder.setInstructions(isb.build());
595             writeFlow(flowBuilder, nodeBuilder);
596         } else {
597             removeFlow(flowBuilder, nodeBuilder);
598         }
599     }
600
601     /**
602      * Adds rule to check legitimate ip/mac pair for each packet from the vm.
603      *
604      * @param dpidLong the dpid
605      * @param localPort the local port
606      * @param srcIp the vm ip address
607      * @param attachedMac the vm mac address
608      * @param protoPortMatchPriority  the priority
609      * @param write is write or delete
610      */
611     public void egressACLAllowTrafficFromVmIpMacPair(Long dpidLong, long localPort,
612              String attachedMac, String srcIp, Integer protoPortMatchPriority, boolean write) {
613
614         String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
615         MatchBuilder matchBuilder = new MatchBuilder();
616         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
617         FlowBuilder flowBuilder = new FlowBuilder();
618         MatchUtils.createSrcL3IPv4MatchWithMac(matchBuilder, new Ipv4Prefix(srcIp),new MacAddress(attachedMac));
619         MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
620         flowBuilder.setMatch(matchBuilder.build());
621
622         LOG.debug("egressACLAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", flowBuilder.getMatch());
623         String flowId = "Egress_Allow_VM_IP_MAC" + "_" + localPort + attachedMac + "_Permit_";
624         // Add Flow Attributes
625         flowBuilder.setId(new FlowId(flowId));
626         FlowKey key = new FlowKey(new FlowId(flowId));
627         flowBuilder.setStrict(false);
628         flowBuilder.setPriority(protoPortMatchPriority);
629         flowBuilder.setBarrier(true);
630         flowBuilder.setTableId(this.getTable());
631         flowBuilder.setKey(key);
632         flowBuilder.setFlowName(flowId);
633         flowBuilder.setHardTimeout(0);
634         flowBuilder.setIdleTimeout(0);
635
636         if (write) {
637             // Instantiate the Builders for the OF Actions and Instructions
638             InstructionBuilder ib = new InstructionBuilder();
639             InstructionsBuilder isb = new InstructionsBuilder();
640             List<Instruction> instructionsList = Lists.newArrayList();
641
642             ib = this.getMutablePipelineInstructionBuilder();
643             ib.setOrder(0);
644             ib.setKey(new InstructionKey(0));
645             instructionsList.add(ib.build());
646             isb.setInstruction(instructionsList);
647
648             LOG.debug("egressACLAllowTrafficFromVmIpMacPair: Instructions contain: {}", ib.getInstruction());
649             // Add InstructionsBuilder to FlowBuilder
650             flowBuilder.setInstructions(isb.build());
651             writeFlow(flowBuilder, nodeBuilder);
652         } else {
653             removeFlow(flowBuilder, nodeBuilder);
654         }
655     }
656     @Override
657     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
658         super.setDependencies(bundleContext.getServiceReference(EgressAclProvider.class.getName()), this);
659     }
660
661     @Override
662     public void setDependencies(Object impl) {}
663 }