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