2 * Copyright (c) 2014, 2015 Red Hat, Inc. and others. All rights reserved.
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
9 package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services;
11 import java.math.BigInteger;
12 import java.util.List;
14 import org.opendaylight.neutron.spi.NeutronSecurityGroup;
15 import org.opendaylight.neutron.spi.NeutronSecurityRule;
16 import org.opendaylight.neutron.spi.Neutron_IPs;
17 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
18 import org.opendaylight.ovsdb.openstack.netvirt.api.EgressAclProvider;
19 import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
20 import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
21 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
22 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
23 import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
24 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
25 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
38 import org.osgi.framework.BundleContext;
39 import org.osgi.framework.ServiceReference;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 import com.google.common.collect.Lists;
45 public class EgressAclService extends AbstractServiceInstance implements EgressAclProvider, ConfigInterface {
47 private static final Logger LOG = LoggerFactory.getLogger(EgressAclService.class);
48 private volatile SecurityServicesManager securityServicesManager;
49 private static final int DHCP_SOURCE_PORT = 67;
50 private static final int DHCP_DESTINATION_PORT = 68;
51 private static final String HOST_MASK = "/32";
53 public EgressAclService() {
54 super(Service.EGRESS_ACL);
57 public EgressAclService(Service service) {
62 public void programPortSecurityAcl(Long dpid, String segmentationId, String attachedMac, long localPort,
63 NeutronSecurityGroup securityGroup,
64 List<Neutron_IPs> srcAddressList, boolean write) {
66 LOG.trace("programPortSecurityAcl: neutronSecurityGroup: {} ", securityGroup);
67 if (securityGroup == null || securityGroup.getSecurityRules() == null) {
71 List<NeutronSecurityRule> portSecurityList = securityGroup.getSecurityRules();
72 /* Iterate over the Port Security Rules in the Port Security Group bound to the port*/
73 for (NeutronSecurityRule portSecurityRule : portSecurityList) {
75 * Neutron Port Security Acl "egress" and "IPv4"
76 * Check that the base conditions for flow based Port Security are true:
77 * Port Security Rule Direction ("egress") and Protocol ("IPv4")
78 * Neutron defines the direction "ingress" as the vSwitch to the VM as defined in:
79 * http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html
82 if ("IPv4".equals(portSecurityRule.getSecurityRuleEthertype())
83 && portSecurityRule.getSecurityRuleDirection().equals("egress")) {
84 LOG.debug("programPortSecurityAcl: Acl Rule matching IPv4 and ingress is: {} ", portSecurityRule);
85 if (null == portSecurityRule.getSecurityRuleProtocol()) {
86 /* TODO Rework on the priority values */
87 egressAclIPv4(dpid, segmentationId, attachedMac,
88 write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
89 } else if (null != portSecurityRule.getSecurityRemoteGroupID()) {
90 //Remote Security group is selected
91 List<Neutron_IPs> remoteSrcAddressList = securityServicesManager
92 .getVmListForSecurityGroup(srcAddressList,portSecurityRule.getSecurityRemoteGroupID());
93 if (null != remoteSrcAddressList) {
94 for (Neutron_IPs vmIp :remoteSrcAddressList ) {
95 switch (portSecurityRule.getSecurityRuleProtocol()) {
97 egressAclTcp(dpid, segmentationId, attachedMac,
98 portSecurityRule,vmIp.getIpAddress(), write,
99 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
102 egressAclUdp(dpid, segmentationId, attachedMac,
103 portSecurityRule,vmIp.getIpAddress(), write,
104 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
106 case MatchUtils.ICMP:
107 egressAclIcmp(dpid, segmentationId, attachedMac,
108 portSecurityRule, vmIp.getIpAddress(),write,
109 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
112 LOG.error("programPortSecurityAcl: Protocol not supported", portSecurityRule);
119 switch (portSecurityRule.getSecurityRuleProtocol()) {
121 egressAclTcp(dpid, segmentationId, attachedMac,
122 portSecurityRule, null, write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
125 egressAclUdp(dpid, segmentationId, attachedMac,
126 portSecurityRule, null, write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
128 case MatchUtils.ICMP:
129 egressAclIcmp(dpid, segmentationId, attachedMac,
130 portSecurityRule, null, write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
133 LOG.error("programPortSecurityAcl: Protocol not supported", portSecurityRule);
138 * Code is refactored to handle all the protocols. More
139 * protocols will be added incrementrally
140 * TODO Connection tracking will be used to track active TCP connections This code
141 * may be reused then.
143 /* if (portSecurityRule.getSecurityRuleEthertype().equalsIgnoreCase("IPv4") &&
144 portSecurityRule.getSecurityRuleDirection().equalsIgnoreCase("egress")) {
145 LOG.debug("Egress IPV4 ACL Port Security Rule: {} ", portSecurityRule);
146 // ToDo: Implement Port Range
149 * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (True)
151 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
152 !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
153 !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
154 (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
155 !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
156 .equalsIgnoreCase("0.0.0.0/0"))) {
158 "Rule #1 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
159 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
160 portSecurityRule.getSecurityRulePortMax(),
161 portSecurityRule.getSecurityRuleRemoteIpPrefix());
162 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
163 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP,
165 egressACLTcpPortWithPrefix(dpid, segmentationId,
166 attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
167 portSecurityRule.getSecurityRuleRemoteIpPrefix(),
168 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
172 * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (True)
174 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
175 !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
176 String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
177 (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
178 !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
179 .equalsIgnoreCase("0.0.0.0/0"))) {
181 "Rule #2 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
182 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
183 portSecurityRule.getSecurityRulePortMax(),
184 portSecurityRule.getSecurityRuleRemoteIpPrefix());
185 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
186 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP,
188 egressACLTcpPortWithPrefix(dpid, segmentationId,
189 attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
190 portSecurityRule.getSecurityRuleRemoteIpPrefix(),
191 Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY);
195 * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True)
197 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
198 String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
199 String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
200 !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
202 "Rule #3 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
203 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
204 portSecurityRule.getSecurityRulePortMax(),
205 portSecurityRule.getSecurityRuleRemoteIpPrefix());
206 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PROTO_PREFIX_MATCH_PRIORITY_DROP,
208 egressACLPermitAllProto(dpid, segmentationId, attachedMac, true,
209 portSecurityRule.getSecurityRuleRemoteIpPrefix(), Constants.PROTO_PREFIX_MATCH_PRIORITY);
213 * TCP Proto (False), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True)
215 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("null") &&
216 String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
217 String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
218 (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") &&
219 !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
220 .equalsIgnoreCase("0.0.0.0/0"))) {
222 "Rule #4 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
223 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
224 portSecurityRule.getSecurityRulePortMax(),
225 portSecurityRule.getSecurityRuleRemoteIpPrefix());
226 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PREFIX_MATCH_PRIORITY_DROP, true);
227 egressACLPermitAllProto(dpid, segmentationId, attachedMac, true,
228 portSecurityRule.getSecurityRuleRemoteIpPrefix(), Constants.PREFIX_MATCH_PRIORITY);
232 * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (False)
234 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
235 !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
236 !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
237 String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
239 "Rule #5 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
240 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
241 portSecurityRule.getSecurityRulePortMax(),
242 portSecurityRule.getSecurityRuleRemoteIpPrefix());
243 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, Constants.PROTO_PORT_MATCH_PRIORITY_DROP,
245 egressACLTcpSyn(dpid, segmentationId,
246 attachedMac, true, portSecurityRule.getSecurityRulePortMin(),
247 Constants.PROTO_PORT_MATCH_PRIORITY);
251 * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (False)
253 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
254 !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
255 String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
256 String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) {
258 "Rule #6 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
259 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
260 portSecurityRule.getSecurityRulePortMax(),
261 portSecurityRule.getSecurityRuleRemoteIpPrefix());
262 egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac,
263 Constants.PROTO_PORT_MATCH_PRIORITY_DROP, true);
264 egressACLTcpSyn(dpid, segmentationId, attachedMac, true,
265 portSecurityRule.getSecurityRulePortMin(), Constants.PROTO_PORT_MATCH_PRIORITY);
269 * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (False or 0.0.0.0/0)
271 if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") &&
272 String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") &&
273 String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") &&
274 ((String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) ||
275 String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix())
276 .equalsIgnoreCase("0.0.0.0/0"))) {
278 "Rule #7 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}",
279 portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(),
280 portSecurityRule.getSecurityRulePortMax(),
281 portSecurityRule.getSecurityRuleRemoteIpPrefix());
282 // No need to drop until UDP/ICMP are implemented
283 // egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, PROTO_MATCH_PRIORITY_DROP, true);
284 egressAllowProto(dpid, segmentationId, attachedMac, true,
285 portSecurityRule.getSecurityRuleProtocol(), Constants.PROTO_MATCH_PRIORITY);
288 LOG.debug("ACL Match combination not found for rule: {}", portSecurityRule);
294 public void programFixedSecurityAcl(Long dpid, String segmentationId, String attachedMac,
295 long localPort, List<Neutron_IPs> srcAddressList,
296 boolean isLastPortinBridge, boolean isComputePort ,boolean write) {
297 // If it is the only port in the bridge add the rule to allow any DHCP client traffic
298 if (isLastPortinBridge) {
299 egressAclDhcpAllowClientTrafficFromVm(dpid, write, Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY);
302 // add rule to drop the DHCP server traffic originating from the vm.
303 egressAclDhcpDropServerTrafficfromVm(dpid, localPort, write,
304 Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP);
305 //Adds rule to check legitimate ip/mac pair for each packet from the vm
306 for (Neutron_IPs srcAddress : srcAddressList) {
307 String addressWithPrefix = srcAddress.getIpAddress() + HOST_MASK;
308 egressAclAllowTrafficFromVmIpMacPair(dpid, localPort, attachedMac, addressWithPrefix,
309 Constants.PROTO_VM_IP_MAC_MATCH_PRIORITY,write);
315 * Allows IPv4 packet egress from the src mac address.
316 * @param dpidLong the dpid
317 * @param segmentationId the segementation id
318 * @param srcMac the src mac address
319 * @param write add or remove
320 * @param protoPortMatchPriority the protocol match priority.
322 private void egressAclIPv4(Long dpidLong, String segmentationId, String srcMac,
323 boolean write, Integer protoPortMatchPriority ) {
324 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
325 MatchBuilder matchBuilder = new MatchBuilder();
326 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
327 String flowId = "Egress_IP" + segmentationId + "_" + srcMac + "_Permit_";
328 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
329 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
333 * Creates a egress match with src macaddress. If dest address is specified
334 * destination specific match will be created. Otherwise a match with a
335 * CIDR will be created.
336 * @param dpidLong the dpid
337 * @param segmentationId the segmentation id
338 * @param srcMac the source mac address.
339 * @param portSecurityRule the security rule in the SG
340 * @param dstAddress the destination IP address
341 * @param write add or delete
342 * @param protoPortMatchPriority the protocol match priroty
344 private void egressAclTcp(Long dpidLong, String segmentationId, String srcMac,
345 NeutronSecurityRule portSecurityRule, String dstAddress,
346 boolean write, Integer protoPortMatchPriority) {
347 MatchBuilder matchBuilder = new MatchBuilder();
348 String flowId = "Egress_Custom_Tcp" + segmentationId + "_" + srcMac + "_";
349 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
350 if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
351 flowId = flowId + portSecurityRule.getSecurityRulePortMin();
352 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.TCP_SHORT, 0,
353 portSecurityRule.getSecurityRulePortMin());
355 /*TODO TCP PortRange Match*/
359 if (null != dstAddress) {
360 flowId = flowId + dstAddress;
361 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
362 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
364 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
365 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
366 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
367 new Ipv4Prefix(portSecurityRule
368 .getSecurityRuleRemoteIpPrefix()));
370 flowId = flowId + "_Permit_";
371 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
372 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
373 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
378 * Creates a egress match with src macaddress. If dest address is specified
379 * destination specific match will be created. Otherwise a match with a
380 * CIDR will be created.
381 * @param dpidLong the dpid
382 * @param segmentationId the segmentation id
383 * @param srcMac the source mac address.
384 * @param portSecurityRule the security rule in the SG
385 * @param dstAddress the source IP address
386 * @param write add or delete
387 * @param protoPortMatchPriority the protocol match priority
389 private void egressAclIcmp(Long dpidLong, String segmentationId, String srcMac,
390 NeutronSecurityRule portSecurityRule, String dstAddress,
391 boolean write, Integer protoPortMatchPriority) {
392 MatchBuilder matchBuilder = new MatchBuilder();
393 String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_"
394 + portSecurityRule.getSecurityRulePortMin().shortValue() + "_"
395 + portSecurityRule.getSecurityRulePortMax().shortValue() + "_";
396 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
397 matchBuilder = MatchUtils.createICMPv4Match(matchBuilder,
398 portSecurityRule.getSecurityRulePortMin().shortValue(),
399 portSecurityRule.getSecurityRulePortMax().shortValue());
400 if (null != dstAddress) {
401 flowId = flowId + dstAddress;
402 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
403 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
404 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
405 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
406 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
407 new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix()));
409 flowId = flowId + "_Permit";
410 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
411 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
412 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
417 * Creates a egress match with src macaddress. If dest address is specified
418 * destination specific match will be created. Otherwise a match with a
419 * CIDR will be created.
420 * @param dpidLong the dpid
421 * @param segmentationId the segmentation id
422 * @param srcMac the source mac address.
423 * @param portSecurityRule the security rule in the SG
424 * @param dstAddress the source IP address
425 * @param write add or delete
426 * @param protoPortMatchPriority the protocol match priroty
428 private void egressAclUdp(Long dpidLong, String segmentationId, String srcMac,
429 NeutronSecurityRule portSecurityRule, String dstAddress,
430 boolean write, Integer protoPortMatchPriority) {
432 MatchBuilder matchBuilder = new MatchBuilder();
433 String flowId = "Eress_UDP" + segmentationId + "_" + srcMac + "_";
434 matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null);
435 if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) {
436 flowId = flowId + portSecurityRule.getSecurityRulePortMin();
437 matchBuilder = MatchUtils.addLayer4Match(matchBuilder, MatchUtils.UDP_SHORT, 0,
438 portSecurityRule.getSecurityRulePortMin());
440 /*TODO UDP PortRange Match*/
444 if (null != dstAddress) {
445 flowId = flowId + dstAddress;
446 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null,
447 MatchUtils.iPv4PrefixFromIPv4Address(dstAddress));
449 } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) {
450 flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix();
451 matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null,
452 new Ipv4Prefix(portSecurityRule
453 .getSecurityRuleRemoteIpPrefix()));
455 flowId = flowId + "_Permit_";
456 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
457 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
458 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
461 public void egressACLDefaultTcpDrop(Long dpidLong, String segmentationId, String attachedMac,
462 int priority, boolean write) {
464 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
465 MatchBuilder matchBuilder = new MatchBuilder();
466 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
467 FlowBuilder flowBuilder = new FlowBuilder();
469 flowBuilder.setMatch(MatchUtils.createSmacTcpPortWithFlagMatch(matchBuilder,
470 attachedMac, Constants.TCP_SYN, segmentationId).build());
471 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
473 String flowId = "TCP_Syn_Egress_Default_Drop_" + segmentationId + "_" + attachedMac;
474 flowBuilder.setId(new FlowId(flowId));
475 FlowKey key = new FlowKey(new FlowId(flowId));
476 flowBuilder.setStrict(false);
477 flowBuilder.setPriority(priority);
478 flowBuilder.setBarrier(true);
479 flowBuilder.setTableId(this.getTable());
480 flowBuilder.setKey(key);
481 flowBuilder.setFlowName(flowId);
482 flowBuilder.setHardTimeout(0);
483 flowBuilder.setIdleTimeout(0);
486 // Instantiate the Builders for the OF Actions and Instructions
487 InstructionBuilder ib = new InstructionBuilder();
488 InstructionsBuilder isb = new InstructionsBuilder();
489 List<Instruction> instructions = Lists.newArrayList();
491 InstructionUtils.createDropInstructions(ib);
493 ib.setKey(new InstructionKey(0));
494 instructions.add(ib.build());
495 // Add InstructionBuilder to the Instruction(s)Builder List
496 isb.setInstruction(instructions);
498 LOG.debug("Instructions contain: {}", ib.getInstruction());
499 // Add InstructionsBuilder to FlowBuilder
500 flowBuilder.setInstructions(isb.build());
501 writeFlow(flowBuilder, nodeBuilder);
503 removeFlow(flowBuilder, nodeBuilder);
507 public void egressACLTcpPortWithPrefix(Long dpidLong, String segmentationId, String attachedMac, boolean write,
508 Integer securityRulePortMin, String securityRuleIpPrefix, Integer protoPortPrefixMatchPriority) {
510 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
511 PortNumber tcpPort = new PortNumber(securityRulePortMin);
512 MatchBuilder matchBuilder = new MatchBuilder();
513 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
514 FlowBuilder flowBuilder = new FlowBuilder();
515 Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
517 flowBuilder.setMatch(MatchUtils
518 .createSmacTcpSynDstIpPrefixTcpPort(matchBuilder, new MacAddress(attachedMac),
519 tcpPort, Constants.TCP_SYN, segmentationId, srcIpPrefix).build());
521 LOG.debug(" MatchBuilder contains: {}", flowBuilder.getMatch());
522 String flowId = "UcastEgress_" + segmentationId + "_" + attachedMac +
523 securityRulePortMin + securityRuleIpPrefix;
524 // Add Flow Attributes
525 flowBuilder.setId(new FlowId(flowId));
526 FlowKey key = new FlowKey(new FlowId(flowId));
527 flowBuilder.setStrict(false);
528 flowBuilder.setPriority(protoPortPrefixMatchPriority);
529 flowBuilder.setBarrier(true);
530 flowBuilder.setTableId(this.getTable());
531 flowBuilder.setKey(key);
532 flowBuilder.setFlowName(flowId);
533 flowBuilder.setHardTimeout(0);
534 flowBuilder.setIdleTimeout(0);
537 // Instantiate the Builders for the OF Actions and Instructions
538 InstructionsBuilder isb = new InstructionsBuilder();
539 List<Instruction> instructionsList = Lists.newArrayList();
541 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
543 ib.setKey(new InstructionKey(0));
544 instructionsList.add(ib.build());
545 isb.setInstruction(instructionsList);
547 LOG.debug("Instructions contain: {}", ib.getInstruction());
548 // Add InstructionsBuilder to FlowBuilder
549 flowBuilder.setInstructions(isb.build());
550 writeFlow(flowBuilder, nodeBuilder);
552 removeFlow(flowBuilder, nodeBuilder);
558 public void egressAllowProto(Long dpidLong, String segmentationId, String attachedMac, boolean write,
559 String securityRuleProtcol, Integer protoMatchPriority) {
561 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
562 MatchBuilder matchBuilder = new MatchBuilder();
563 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
564 FlowBuilder flowBuilder = new FlowBuilder();
566 flowBuilder.setMatch(MatchUtils
567 .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null).build());
568 flowBuilder.setMatch(MatchUtils
569 .createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
571 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
572 String flowId = "EgressAllProto_" + segmentationId + "_" +
573 attachedMac + "_AllowEgressTCPSyn_" + securityRuleProtcol;
574 // Add Flow Attributes
575 flowBuilder.setId(new FlowId(flowId));
576 FlowKey key = new FlowKey(new FlowId(flowId));
577 flowBuilder.setStrict(false);
578 flowBuilder.setPriority(protoMatchPriority);
579 flowBuilder.setBarrier(true);
580 flowBuilder.setTableId(this.getTable());
581 flowBuilder.setKey(key);
582 flowBuilder.setFlowName(flowId);
583 flowBuilder.setHardTimeout(0);
584 flowBuilder.setIdleTimeout(0);
587 // Instantiate the Builders for the OF Actions and Instructions
588 InstructionsBuilder isb = new InstructionsBuilder();
589 List<Instruction> instructionsList = Lists.newArrayList();
591 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
593 ib.setKey(new InstructionKey(0));
594 instructionsList.add(ib.build());
595 isb.setInstruction(instructionsList);
597 LOG.debug("Instructions contain: {}", ib.getInstruction());
598 // Add InstructionsBuilder to FlowBuilder
599 flowBuilder.setInstructions(isb.build());
600 writeFlow(flowBuilder, nodeBuilder);
602 removeFlow(flowBuilder, nodeBuilder);
606 public void egressACLPermitAllProto(Long dpidLong, String segmentationId, String attachedMac,
607 boolean write, String securityRuleIpPrefix, Integer protoPortMatchPriority) {
609 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
610 MatchBuilder matchBuilder = new MatchBuilder();
611 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
612 FlowBuilder flowBuilder = new FlowBuilder();
614 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId))
616 if (securityRuleIpPrefix != null) {
617 Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix);
618 flowBuilder.setMatch(MatchUtils
619 .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, srcIpPrefix)
622 flowBuilder.setMatch(MatchUtils
623 .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null)
626 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
627 String flowId = "Egress_Proto_ACL" + segmentationId + "_" +
628 attachedMac + "_Permit_" + securityRuleIpPrefix;
629 // Add Flow Attributes
630 flowBuilder.setId(new FlowId(flowId));
631 FlowKey key = new FlowKey(new FlowId(flowId));
632 flowBuilder.setStrict(false);
633 flowBuilder.setPriority(protoPortMatchPriority);
634 flowBuilder.setBarrier(true);
635 flowBuilder.setTableId(this.getTable());
636 flowBuilder.setKey(key);
637 flowBuilder.setFlowName(flowId);
638 flowBuilder.setHardTimeout(0);
639 flowBuilder.setIdleTimeout(0);
642 // Instantiate the Builders for the OF Actions and Instructions
643 InstructionsBuilder isb = new InstructionsBuilder();
644 List<Instruction> instructionsList = Lists.newArrayList();
646 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
648 ib.setKey(new InstructionKey(0));
649 instructionsList.add(ib.build());
650 isb.setInstruction(instructionsList);
652 LOG.debug("Instructions contain: {}", ib.getInstruction());
653 // Add InstructionsBuilder to FlowBuilder
654 flowBuilder.setInstructions(isb.build());
655 writeFlow(flowBuilder, nodeBuilder);
657 removeFlow(flowBuilder, nodeBuilder);
662 public void egressACLTcpSyn(Long dpidLong, String segmentationId, String attachedMac, boolean write,
663 Integer securityRulePortMin, Integer protoPortMatchPriority) {
665 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
666 PortNumber tcpPort = new PortNumber(securityRulePortMin);
667 MatchBuilder matchBuilder = new MatchBuilder();
668 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
669 FlowBuilder flowBuilder = new FlowBuilder();
671 flowBuilder.setMatch(MatchUtils.createSmacTcpSyn(matchBuilder, attachedMac, tcpPort,
672 Constants.TCP_SYN, segmentationId).build());
674 LOG.debug("MatchBuilder contains: {}", flowBuilder.getMatch());
675 String flowId = "Ucast_this.getTable()" + segmentationId + "_" + attachedMac + securityRulePortMin;
676 // Add Flow Attributes
677 flowBuilder.setId(new FlowId(flowId));
678 FlowKey key = new FlowKey(new FlowId(flowId));
679 flowBuilder.setStrict(false);
680 flowBuilder.setPriority(protoPortMatchPriority);
681 flowBuilder.setBarrier(true);
682 flowBuilder.setTableId(this.getTable());
683 flowBuilder.setKey(key);
684 flowBuilder.setFlowName(flowId);
685 flowBuilder.setHardTimeout(0);
686 flowBuilder.setIdleTimeout(0);
689 // Instantiate the Builders for the OF Actions and Instructions
690 InstructionsBuilder isb = new InstructionsBuilder();
691 List<Instruction> instructionsList = Lists.newArrayList();
693 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
695 ib.setKey(new InstructionKey(0));
696 instructionsList.add(ib.build());
697 isb.setInstruction(instructionsList);
699 LOG.debug("Instructions contain: {}", ib.getInstruction());
700 // Add InstructionsBuilder to FlowBuilder
701 flowBuilder.setInstructions(isb.build());
702 writeFlow(flowBuilder, nodeBuilder);
704 removeFlow(flowBuilder, nodeBuilder);
709 * Adds flow to allow any DHCP client traffic.
711 * @param dpidLong the dpid
712 * @param write whether to write or delete the flow
713 * @param protoPortMatchPriority the priority
715 private void egressAclDhcpAllowClientTrafficFromVm(Long dpidLong,
716 boolean write, Integer protoPortMatchPriority) {
718 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
719 MatchBuilder matchBuilder = new MatchBuilder();
720 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
722 MatchUtils.createDhcpMatch(matchBuilder, DHCP_DESTINATION_PORT, DHCP_SOURCE_PORT).build();
723 LOG.debug("egressAclDHCPAllowClientTrafficFromVm: MatchBuilder contains: {}", matchBuilder);
724 String flowId = "Egress_DHCP_Client" + "_Permit_";
725 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
729 * Adds rule to prevent DHCP spoofing by the vm attached to the port.
731 * @param dpidLong the dpid
732 * @param localPort the local port
733 * @param write is write or delete
734 * @param protoPortMatchPriority the priority
736 private void egressAclDhcpDropServerTrafficfromVm(Long dpidLong, long localPort,
737 boolean write, Integer protoPortMatchPriority) {
739 MatchBuilder matchBuilder = new MatchBuilder();
740 //FlowBuilder flowBuilder = new FlowBuilder();
741 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
742 MatchUtils.createDhcpMatch(matchBuilder, DHCP_SOURCE_PORT, DHCP_DESTINATION_PORT).build();
743 LOG.debug("egressAclDHCPDropServerTrafficfromVM: MatchBuilder contains: {}", matchBuilder);
744 String flowId = "Egress_DHCP_Server" + "_" + localPort + "_DROP_";
745 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
746 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
747 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, true);
752 * Adds rule to check legitimate ip/mac pair for each packet from the vm.
754 * @param dpidLong the dpid
755 * @param localPort the local port
756 * @param srcIp the vm ip address
757 * @param attachedMac the vm mac address
758 * @param protoPortMatchPriority the priority
759 * @param write is write or delete
761 private void egressAclAllowTrafficFromVmIpMacPair(Long dpidLong, long localPort,
762 String attachedMac, String srcIp,
763 Integer protoPortMatchPriority, boolean write) {
764 MatchBuilder matchBuilder = new MatchBuilder();
765 MatchUtils.createSrcL3Ipv4MatchWithMac(matchBuilder, new Ipv4Prefix(srcIp),new MacAddress(attachedMac));
766 MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort);
767 LOG.debug("egressAclAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", matchBuilder);
768 String flowId = "Egress_Allow_VM_IP_MAC" + "_" + localPort + attachedMac + "_Permit_";
769 String nodeName = Constants.OPENFLOW_NODE_PREFIX + dpidLong;
770 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
771 syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false);
776 * Add or remove flow to the node.
778 * @param flowId the the flow id
779 * @param nodeBuilder the node builder
780 * @param matchBuilder the matchbuilder
781 * @param protoPortMatchPriority the protocol priority
782 * @param write whether it is a write
783 * @param drop whether it is a drop or forward
785 private void syncFlow(String flowId, NodeBuilder nodeBuilder,
786 MatchBuilder matchBuilder,Integer protoPortMatchPriority,
787 boolean write,boolean drop) {
788 FlowBuilder flowBuilder = new FlowBuilder();
789 flowBuilder.setMatch(matchBuilder.build());
790 flowBuilder.setId(new FlowId(flowId));
791 FlowKey key = new FlowKey(new FlowId(flowId));
792 flowBuilder.setStrict(false);
793 flowBuilder.setPriority(protoPortMatchPriority);
794 flowBuilder.setBarrier(true);
795 flowBuilder.setTableId(this.getTable());
796 flowBuilder.setKey(key);
797 flowBuilder.setFlowName(flowId);
798 flowBuilder.setHardTimeout(0);
799 flowBuilder.setIdleTimeout(0);
802 // Instantiate the Builders for the OF Actions and Instructions
804 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
806 InstructionUtils.createDropInstructions(ib);
809 ib.setKey(new InstructionKey(0));
810 InstructionsBuilder isb = new InstructionsBuilder();
811 List<Instruction> instructionsList = Lists.newArrayList();
812 instructionsList.add(ib.build());
813 isb.setInstruction(instructionsList);
814 flowBuilder.setInstructions(isb.build());
815 writeFlow(flowBuilder, nodeBuilder);
817 removeFlow(flowBuilder, nodeBuilder);
825 public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
826 super.setDependencies(bundleContext.getServiceReference(EgressAclProvider.class.getName()), this);
827 securityServicesManager =
828 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
832 public void setDependencies(Object impl) {}