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