From 6f3ee61072b2b3830e0a8f1b5fad49c92b8ac387 Mon Sep 17 00:00:00 2001 From: Brent Salisbury Date: Sun, 31 Aug 2014 21:41:31 -0400 Subject: [PATCH] ACL services for OS/OVS Patch #1:Ingress ACLs Patch #2:Egress ACLs Patch #3:Rebase and typos Patch #4:Service exports patching Patch #5:Added IngressACL Interface and verified flowmods Patch #6:Deleted random .diff file in last commit TODO: -Break egress out of the IngressACLService into EgressACLService Easier to tshoot colapsed. -CRUD updates and deletes. -Refactor GOTO instructs w/the pipeline mutator fromt the abstract services parent for Egress ACL (completed for Ingress) Change-Id: I2a7bea87e7d75b6b02c8ff6a43b60f881c4ade02 Signed-off-by: Brent Salisbury --- .../netvirt/providers/Activator.java | 16 +- .../openflow13/AbstractServiceInstance.java | 2 +- .../providers/openflow13/OF13Provider.java | 47 +- .../services/IngressAclService.java | 868 +++++++++++++++++- .../ovsdb/openstack/netvirt/Activator.java | 16 +- .../netvirt/api/IngressAclProvider.java | 32 + .../netvirt/api/SecurityServicesManager.java | 35 + .../netvirt/impl/SecurityServicesImpl.java | 90 ++ .../utils/mdsal/openflow/MatchUtils.java | 473 ++++++++++ 9 files changed, 1548 insertions(+), 31 deletions(-) create mode 100644 openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/IngressAclProvider.java create mode 100644 openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/SecurityServicesManager.java create mode 100644 openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/SecurityServicesImpl.java diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/Activator.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/Activator.java index 8638b34b5..ae68d15fb 100644 --- a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/Activator.java +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/Activator.java @@ -21,10 +21,12 @@ import org.opendaylight.ovsdb.openstack.netvirt.api.ArpProvider; import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager; import org.opendaylight.ovsdb.openstack.netvirt.api.Constants; import org.opendaylight.ovsdb.openstack.netvirt.api.InboundNatProvider; +import org.opendaylight.ovsdb.openstack.netvirt.api.IngressAclProvider; import org.opendaylight.ovsdb.openstack.netvirt.api.L3ForwardingProvider; import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProvider; import org.opendaylight.ovsdb.openstack.netvirt.api.OutboundNatProvider; import org.opendaylight.ovsdb.openstack.netvirt.api.RoutingProvider; +import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager; import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager; import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow10.OF10Provider; import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance; @@ -160,9 +162,13 @@ public class Activator extends ComponentActivatorAbstractBase { c.add(createServiceDependency() .setService(TenantNetworkManager.class) .setRequired(true)); + c.add(createServiceDependency() + .setService(SecurityServicesManager.class) + .setRequired(true)); c.add(createServiceDependency().setService(OvsdbConfigurationService.class).setRequired(true)); c.add(createServiceDependency().setService(OvsdbConnectionService.class).setRequired(true)); c.add(createServiceDependency().setService(MdsalConsumer.class).setRequired(true)); + c.add(createServiceDependency().setService(IngressAclProvider.class).setRequired(true)); } if (imp.equals(PipelineOrchestratorImpl.class)) { @@ -206,7 +212,8 @@ public class Activator extends ComponentActivatorAbstractBase { Properties properties = new Properties(); properties.put(AbstractServiceInstance.SERVICE_PROPERTY, Service.INGRESS_ACL); properties.put(Constants.PROVIDER_NAME_PROPERTY, OF13Provider.NAME); - c.setInterface(AbstractServiceInstance.class.getName(), properties); + c.setInterface(new String[]{AbstractServiceInstance.class.getName(), + IngressAclProvider.class.getName()}, properties); } if (imp.equals(LoadBalancerService.class)) { @@ -246,13 +253,6 @@ public class Activator extends ComponentActivatorAbstractBase { c.setInterface(AbstractServiceInstance.class.getName(), properties); } - if (imp.equals(IngressAclService.class)) { - Properties properties = new Properties(); - properties.put(AbstractServiceInstance.SERVICE_PROPERTY, Service.INGRESS_ACL); - properties.put(Constants.PROVIDER_NAME_PROPERTY, OF13Provider.NAME); - c.setInterface(AbstractServiceInstance.class.getName(), properties); - } - if (imp.equals(OutboundNatService.class)) { Properties properties = new Properties(); properties.put(AbstractServiceInstance.SERVICE_PROPERTY, Service.OUTBOUND_NAT); diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/AbstractServiceInstance.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/AbstractServiceInstance.java index 9fdc6fb3c..efc39c0a6 100644 --- a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/AbstractServiceInstance.java +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/AbstractServiceInstance.java @@ -120,7 +120,7 @@ public abstract class AbstractServiceInstance implements OpendaylightInventoryLi thread.start(); } - private NodeBuilder createNodeBuilder(String nodeId) { + public NodeBuilder createNodeBuilder(String nodeId) { NodeBuilder builder = new NodeBuilder(); builder.setId(new NodeId(nodeId)); builder.setKey(new NodeKey(builder.getId())); diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/OF13Provider.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/OF13Provider.java index 648385866..6248a95ab 100644 --- a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/OF13Provider.java +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/OF13Provider.java @@ -9,8 +9,13 @@ */ package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13; -import com.google.common.base.Optional; -import com.google.common.util.concurrent.CheckedFuture; +import java.math.BigInteger; +import java.net.InetAddress; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ExecutionException; + import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; @@ -18,25 +23,28 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork; +import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.utils.HexEncode; import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.sal.utils.StatusCode; import org.opendaylight.ovsdb.lib.notation.Row; import org.opendaylight.ovsdb.lib.notation.UUID; -import org.opendaylight.ovsdb.openstack.netvirt.api.Constants; import org.opendaylight.ovsdb.openstack.netvirt.NetworkHandler; import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager; +import org.opendaylight.ovsdb.openstack.netvirt.api.Constants; +import org.opendaylight.ovsdb.openstack.netvirt.api.IngressAclProvider; import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProvider; +import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager; import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager; import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService; import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService; -import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils; -import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils; import org.opendaylight.ovsdb.plugin.api.StatusWithUuid; import org.opendaylight.ovsdb.schema.openvswitch.Bridge; import org.opendaylight.ovsdb.schema.openvswitch.Interface; import org.opendaylight.ovsdb.schema.openvswitch.Port; +import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils; +import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCase; @@ -84,19 +92,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.math.BigInteger; -import java.net.InetAddress; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ExecutionException; +import com.google.common.util.concurrent.CheckedFuture; /** * Open vSwitch OpenFlow 1.3 Networking Provider for OpenStack Neutron @@ -116,6 +119,8 @@ public class OF13Provider implements NetworkingProvider { private volatile OvsdbConfigurationService ovsdbConfigurationService; private volatile OvsdbConnectionService connectionService; private volatile MdsalConsumer mdsalConsumer; + private volatile SecurityServicesManager securityServicesManager; + private volatile IngressAclProvider ingressAclProvider; public static final String NAME = "OF13Provider"; @@ -822,7 +827,19 @@ public class OF13Provider implements NetworkingProvider { if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VLAN)) { logger.debug("Program local vlan rules for interface {}", intf.getName()); programLocalVlanRules(node, dpid, segmentationId, attachedMac, localPort); - } else if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) || + } + /* If the network type is tunnel based (VXLAN/GRRE/etc) with Neutron Port Security ACLs */ + if ((networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) || networkType.equalsIgnoreCase + (NetworkHandler.NETWORK_TYPE_VXLAN)) && securityServicesManager.isPortSecurityReady(intf)) { + logger.debug("Neutron port has a Port Security Group"); + /* Retrieve the security group UUID from the Neutron Port */ + NeutronSecurityGroup securityGroupInPort = securityServicesManager.getSecurityGroupInPort(intf); + logger.debug("Program Local rules for networkType: {} does contain a Port Security Group: {} " + + "to be installed on DPID: {}", networkType, securityGroupInPort, dpid); + ingressAclProvider.programPortSecurityACL(node, dpid, segmentationId, attachedMac, localPort, + securityGroupInPort); + } + else if (networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_GRE) || networkType.equalsIgnoreCase(NetworkHandler.NETWORK_TYPE_VXLAN)) { logger.debug("Program local bridge rules for interface {}", intf.getName()); programLocalBridgeRules(node, dpid, segmentationId, attachedMac, localPort); diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/IngressAclService.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/IngressAclService.java index b77643a71..b8ceb9520 100644 --- a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/IngressAclService.java +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/IngressAclService.java @@ -9,10 +9,59 @@ */ package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services; +import java.math.BigInteger; +import java.util.List; + +import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup; +import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityRule; +import org.opendaylight.controller.sal.core.Node; +import org.opendaylight.ovsdb.openstack.netvirt.api.IngressAclProvider; import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance; import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service; +import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils; +import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Lists; + +public class IngressAclService extends AbstractServiceInstance implements IngressAclProvider { + + static final Logger logger = LoggerFactory.getLogger(IngressAclService.class); + public static final Integer PROTO_MATCH_PRIORITY_DROP = 36006; + public static final Integer PROTO_PORT_MATCH_PRIORITY_DROP = 36005; + public static final Integer PREFIX_MATCH_PRIORITY_DROP = 36004; + public static final Integer PROTO_PREFIX_MATCH_PRIORITY_DROP = 36003; + public static final Integer PREFIX_PORT_MATCH_PRIORITY_DROP = 36002; + public static final Integer PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP = 36001; + + public static final Integer PROTO_MATCH_PRIORITY = 61010; + public static final Integer PREFIX_MATCH_PRIORITY = 61009; + public static final Integer PROTO_PREFIX_MATCH_PRIORITY = 61008; + public static final Integer PROTO_PORT_MATCH_PRIORITY = 61007; + public static final Integer PROTO_PORT_PREFIX_MATCH_PRIORITY = 61007; + + public static final int TCP_SYN = 0x002; + public static final short INGRESS_ACL = 40; // Flows Destined to the VM Port go here + // TODO: break out egress to the egress table and create a parent for both ingress/egress + public static final short EGRESS_ACL = 100; // Flows Sourced from the VM Port go here + public static final short OUTBOUND_SNAT = 110; // Ingress ACL table drains traffic to this table + + private static final String OPENFLOW = "openflow:"; + private static Long groupId = 1L; -public class IngressAclService extends AbstractServiceInstance { public IngressAclService() { super(Service.INGRESS_ACL); } @@ -22,7 +71,820 @@ public class IngressAclService extends AbstractServiceInstance { } @Override - public boolean isBridgeInPipeline (String nodeId) { + public boolean isBridgeInPipeline(String nodeId) { return true; } -} \ No newline at end of file + + @Override + public void programPortSecurityACL(Node node, Long dpid, String segmentationId, String attachedMac, + long localPort, NeutronSecurityGroup securityGroup) { + + logger.trace("programLocalBridgeRulesWithSec neutronSecurityGroup: {} ", securityGroup); + List portSecurityList = securityGroup.getSecurityRules(); + /* Iterate over the Port Security Rules in the Port Security Group bound to the port*/ + for (NeutronSecurityRule portSecurityRule : portSecurityList) { + /** + * Neutron Port Security ACL "ingress" and "IPv4" + * + * Check that the base conditions for flow based Port Security are true: + * Port Security Rule Direction ("ingress") and Protocol ("IPv4") + * Neutron defines the direction "ingress" as the vSwitch to the VM as defined in: + * http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html + * + */ + if (portSecurityRule.getSecurityRuleEthertype().equalsIgnoreCase("IPv4") && + portSecurityRule.getSecurityRuleDirection().equalsIgnoreCase("ingress")) { + logger.debug("ACL Rule matching IPv4 and ingress is: {} ", portSecurityRule); + /** + * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (True) + */ + if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") && + !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") && + (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") && + !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()) + .equalsIgnoreCase("0.0.0.0/0"))) { + logger.debug("Rule #1 ingress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}", + portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRulePortMax(), + portSecurityRule.getSecurityRuleRemoteIpPrefix()); + ingressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, + PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP, + true); + ingressACLTcpPortWithPrefix(dpid, segmentationId, + attachedMac, true, portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRuleRemoteIpPrefix(), PROTO_PORT_PREFIX_MATCH_PRIORITY); + continue; + } + /** + * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (True) + */ + if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") && + !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") && + (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") && + !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()) + .equalsIgnoreCase("0.0.0.0/0"))) { + logger.debug("Rule #2 ingress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}", + portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRulePortMax(), + portSecurityRule.getSecurityRuleRemoteIpPrefix()); + ingressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, + PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP, + true); + ingressACLTcpPortWithPrefix(dpid, segmentationId, + attachedMac, true, portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRuleRemoteIpPrefix(), PROTO_PORT_PREFIX_MATCH_PRIORITY); + continue; + } + /** + * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True) + */ + if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") && + String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") && + !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) { + logger.debug("Rule #3 ingress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}", + portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRulePortMax(), + portSecurityRule.getSecurityRuleRemoteIpPrefix()); + ingressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, PROTO_PREFIX_MATCH_PRIORITY_DROP, + true); + ingressACLPermitAllProto(dpid, segmentationId, attachedMac, true, + portSecurityRule.getSecurityRuleRemoteIpPrefix(), PROTO_PREFIX_MATCH_PRIORITY); + continue; + } + /** + * TCP Proto (False), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True) + */ + if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") && + !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()) + .equalsIgnoreCase("0.0.0.0/0"))) { + logger.debug("Rule #4 ingress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}", + portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRulePortMax(), + portSecurityRule.getSecurityRuleRemoteIpPrefix()); + ingressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, PREFIX_MATCH_PRIORITY_DROP, true); + ingressACLPermitAllProto(dpid, segmentationId, attachedMac, true, + portSecurityRule.getSecurityRuleRemoteIpPrefix(), PREFIX_MATCH_PRIORITY); + continue; + } + /** + * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (False) + */ + if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") && + !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) { + logger.debug("Rule #5 ingress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}", + portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRulePortMax(), + portSecurityRule.getSecurityRuleRemoteIpPrefix()); + ingressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, PROTO_PORT_MATCH_PRIORITY_DROP, + true); + ingressACLTcpSyn(dpid, segmentationId, + attachedMac, true, portSecurityRule.getSecurityRulePortMin(), + PREFIX_PORT_MATCH_PRIORITY_DROP); + continue; + } + /** + * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (False) + */ + if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") && + !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) { + logger.debug("Rule #6 ingress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}", + portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRulePortMax(), + portSecurityRule.getSecurityRuleRemoteIpPrefix()); + ingressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, + PROTO_PORT_MATCH_PRIORITY_DROP, true); + ingressACLTcpSyn(dpid, segmentationId, attachedMac, true, + portSecurityRule.getSecurityRulePortMin(), PROTO_PORT_MATCH_PRIORITY); + continue; + } + /** + * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (False or 0.0.0.0/0) + */ + if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") && + String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") && + ((String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) || + String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()) + .equalsIgnoreCase("0.0.0.0/0"))) { + logger.debug("Rule #7 ingress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}", + portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRulePortMax(), + portSecurityRule.getSecurityRuleRemoteIpPrefix()); + // No need to drop until UDP/ICMP are implemented + // ingressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, PROTO_MATCH_PRIORITY_DROP, true); + handleIngressAllowProto(dpid, segmentationId, attachedMac, true, + portSecurityRule.getSecurityRuleProtocol(), PROTO_MATCH_PRIORITY); + continue; + } + logger.debug("Ingress ACL Match combination not found for rule: {}", portSecurityRule); + } + + /** + * Neutron Port Security ACL "egress" and "IPv4" + * + * Check that the base conditions for flow based Port Security are true: + * Port Security Rule Direction ("egress") and Protocol ("IPv4") + * Neutron defines the direction "ingress" as the vSwitch to the VM as defined in: + * http://docs.openstack.org/api/openstack-network/2.0/content/security_groups.html + * + */ + if (portSecurityRule.getSecurityRuleEthertype().equalsIgnoreCase("IPv4") && + portSecurityRule.getSecurityRuleDirection().equalsIgnoreCase("egress")) { + logger.debug("Egress IPV4 ACL Port Security Rule: {} ", portSecurityRule); + // TODO Move to EgressAclService and Implement Port Range + + /** + * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (True) + */ + if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") && + !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") && + (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") && + !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()) + .equalsIgnoreCase("0.0.0.0/0"))) { + logger.debug("Rule #1 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}", + portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRulePortMax(), + portSecurityRule.getSecurityRuleRemoteIpPrefix()); + egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, + PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP, + true); + egressACLTcpPortWithPrefix(dpid, segmentationId, + attachedMac, true, portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRuleRemoteIpPrefix(), PROTO_PORT_PREFIX_MATCH_PRIORITY); + continue; + } + /** + * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (True) + */ + if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") && + !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") && + (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") && + !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()) + .equalsIgnoreCase("0.0.0.0/0"))) { + logger.debug("Rule #2 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}", + portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRulePortMax(), + portSecurityRule.getSecurityRuleRemoteIpPrefix()); + egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, + PROTO_PORT_PREFIX_MATCH_PRIORITY_DROP, + true); + egressACLTcpPortWithPrefix(dpid, segmentationId, + attachedMac, true, portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRuleRemoteIpPrefix(), PROTO_PORT_PREFIX_MATCH_PRIORITY); + continue; + } + /** + * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True) + */ + if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") && + String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") && + !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) { + logger.debug("Rule #3 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}", + portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRulePortMax(), + portSecurityRule.getSecurityRuleRemoteIpPrefix()); + egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, PROTO_PREFIX_MATCH_PRIORITY_DROP, + true); + egressACLPermitAllProto(dpid, segmentationId, attachedMac, true, + portSecurityRule.getSecurityRuleRemoteIpPrefix(), PROTO_PREFIX_MATCH_PRIORITY); + continue; + } + /** + * TCP Proto (False), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (True) + */ + if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + (!String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null") && + !String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()) + .equalsIgnoreCase("0.0.0.0/0"))) { + logger.debug("Rule #4 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}", + portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRulePortMax(), + portSecurityRule.getSecurityRuleRemoteIpPrefix()); + egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, PREFIX_MATCH_PRIORITY_DROP, true); + egressACLPermitAllProto(dpid, segmentationId, attachedMac, true, + portSecurityRule.getSecurityRuleRemoteIpPrefix(), PREFIX_MATCH_PRIORITY); + continue; + } + /** + * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (True), IP Prefix (False) + */ + if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") && + !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + !String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) { + logger.debug("Rule #5 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}", + portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRulePortMax(), + portSecurityRule.getSecurityRuleRemoteIpPrefix()); + egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, PROTO_PORT_MATCH_PRIORITY_DROP, + true); + egressACLTcpSyn(dpid, segmentationId, + attachedMac, true, portSecurityRule.getSecurityRulePortMin(), PROTO_PORT_MATCH_PRIORITY); + continue; + } + /** + * TCP Proto (True), TCP Port Minimum (True), TCP Port Max (False), IP Prefix (False) + */ + if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") && + !String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) { + logger.debug("Rule #6 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}", + portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRulePortMax(), + portSecurityRule.getSecurityRuleRemoteIpPrefix()); + egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, + PROTO_PORT_MATCH_PRIORITY_DROP, true); + egressACLTcpSyn(dpid, segmentationId, attachedMac, true, + portSecurityRule.getSecurityRulePortMin(), PROTO_PORT_MATCH_PRIORITY); + continue; + } + /** + * TCP Proto (True), TCP Port Minimum (False), TCP Port Max (False), IP Prefix (False or 0.0.0.0/0) + */ + if (String.valueOf(portSecurityRule.getSecurityRuleProtocol()).equalsIgnoreCase("tcp") && + String.valueOf(portSecurityRule.getSecurityRulePortMin()).equalsIgnoreCase("null") && + String.valueOf(portSecurityRule.getSecurityRulePortMax()).equalsIgnoreCase("null") && + ((String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()).equalsIgnoreCase("null")) || + String.valueOf(portSecurityRule.getSecurityRuleRemoteIpPrefix()) + .equalsIgnoreCase("0.0.0.0/0"))) { + logger.debug("Rule #7 egress PortSec Rule Matches -> TCP Protocol: {}, TCP Port Min: {}, TCP Port Max: {}, IP Prefix: {}", + portSecurityRule.getSecurityRuleProtocol(), portSecurityRule.getSecurityRulePortMin(), + portSecurityRule.getSecurityRulePortMax(), + portSecurityRule.getSecurityRuleRemoteIpPrefix()); + // No need to drop until UDP/ICMP are implemented + // egressACLDefaultTcpDrop(dpid, segmentationId, attachedMac, PROTO_MATCH_PRIORITY_DROP, true); + egressAllowProto(dpid, segmentationId, attachedMac, true, + portSecurityRule.getSecurityRuleProtocol(), PROTO_MATCH_PRIORITY); + continue; + } + logger.debug("ACL Match combination not found for rule: {}", portSecurityRule); + + } + } + } + + public void ingressACLTcpSyn(Long dpidLong, String segmentationId, String attachedMac, boolean write, + Integer securityRulePortMin, Integer protoPortMatchPriority) { + + String nodeName = OPENFLOW + dpidLong; + PortNumber tcpPort = new PortNumber(securityRulePortMin); + MatchBuilder matchBuilder = new MatchBuilder(); + NodeBuilder nodeBuilder = createNodeBuilder(nodeName); + FlowBuilder flowBuilder = new FlowBuilder(); + + flowBuilder.setMatch(MatchUtils.createDmacTcpSynMatch(matchBuilder, attachedMac, tcpPort, + TCP_SYN, segmentationId).build()); + + logger.debug("ingressACLTcpSyn MatchBuilder contains: {}", flowBuilder.getMatch()); + String flowId = "UcastOut_ACL2" + segmentationId + "_" + attachedMac + securityRulePortMin; + // Add Flow Attributes + flowBuilder.setId(new FlowId(flowId)); + FlowKey key = new FlowKey(new FlowId(flowId)); + flowBuilder.setStrict(false); + flowBuilder.setPriority(protoPortMatchPriority); + flowBuilder.setBarrier(true); + flowBuilder.setTableId(INGRESS_ACL); + flowBuilder.setKey(key); + flowBuilder.setFlowName(flowId); + flowBuilder.setHardTimeout(0); + flowBuilder.setIdleTimeout(0); + + if (write) { + // Instantiate the Builders for the OF Actions and Instructions + InstructionBuilder ib = new InstructionBuilder(); + InstructionsBuilder isb = new InstructionsBuilder(); + List instructionsList = Lists.newArrayList(); + + ib = this.getMutablePipelineInstructionBuilder(); + ib.setOrder(0); + ib.setKey(new InstructionKey(0)); + instructionsList.add(ib.build()); + isb.setInstruction(instructionsList); + + logger.debug("Instructions are: {}", ib.getInstruction()); + // Add InstructionsBuilder to FlowBuilder + flowBuilder.setInstructions(isb.build()); + writeFlow(flowBuilder, nodeBuilder); + } else { + // removeFlow(flowBuilder, nodeBuilder); + } + } + + public void ingressACLTcpPortWithPrefix(Long dpidLong, String segmentationId, String attachedMac, + boolean write, Integer securityRulePortMin, String securityRuleIpPrefix, + Integer protoPortPrefixMatchPriority) { + + String nodeName = OPENFLOW + dpidLong; + PortNumber tcpPort = new PortNumber(securityRulePortMin); + + MatchBuilder matchBuilder = new MatchBuilder(); + NodeBuilder nodeBuilder = this.createNodeBuilder(nodeName); + FlowBuilder flowBuilder = new FlowBuilder(); + Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix); + + flowBuilder.setMatch(MatchUtils + .createDmacTcpSynDstIpPrefixTcpPort(matchBuilder, new MacAddress(attachedMac), + tcpPort, TCP_SYN, segmentationId, srcIpPrefix).build()); + + logger.debug(" MatchBuilder contains: {}", flowBuilder.getMatch()); + String flowId = "UcastOut2_" + segmentationId + "_" + attachedMac + + securityRulePortMin + securityRuleIpPrefix; + // Add Flow Attributes + flowBuilder.setId(new FlowId(flowId)); + FlowKey key = new FlowKey(new FlowId(flowId)); + flowBuilder.setStrict(false); + flowBuilder.setPriority(protoPortPrefixMatchPriority); + flowBuilder.setBarrier(true); + flowBuilder.setTableId(INGRESS_ACL); + flowBuilder.setKey(key); + flowBuilder.setFlowName(flowId); + flowBuilder.setHardTimeout(0); + flowBuilder.setIdleTimeout(0); + + if (write) { + // Instantiate the Builders for the OF Actions and Instructions + InstructionBuilder ib = new InstructionBuilder(); + InstructionsBuilder isb = new InstructionsBuilder(); + + List instructionsList = Lists.newArrayList(); + ib = this.getMutablePipelineInstructionBuilder(); + ib.setOrder(0); + ib.setKey(new InstructionKey(0)); + instructionsList.add(ib.build()); + isb.setInstruction(instructionsList); + + logger.debug("Instructions contain: {}", ib.getInstruction()); + // Add InstructionsBuilder to FlowBuilder + flowBuilder.setInstructions(isb.build()); + writeFlow(flowBuilder, nodeBuilder); + } else { + // removeFlow(flowBuilder, nodeBuilder); + } + } + + public void handleIngressAllowProto(Long dpidLong, String segmentationId, String attachedMac, boolean write, + String securityRuleProtcol, Integer protoMatchPriority) { + + String nodeName = OPENFLOW + dpidLong; + + MatchBuilder matchBuilder = new MatchBuilder(); + NodeBuilder nodeBuilder = createNodeBuilder(nodeName); + FlowBuilder flowBuilder = new FlowBuilder(); + + flowBuilder.setMatch(MatchUtils + .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null).build()); + flowBuilder.setMatch(MatchUtils + .createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build()); + logger.debug("MatchBuilder contains: {}", flowBuilder.getMatch()); + + String flowId = "UcastOut_" + segmentationId + "_" + + attachedMac + "_AllowTCPSynPrefix_" + securityRuleProtcol; + // Add Flow Attributes + flowBuilder.setId(new FlowId(flowId)); + FlowKey key = new FlowKey(new FlowId(flowId)); + flowBuilder.setStrict(false); + flowBuilder.setPriority(protoMatchPriority); + flowBuilder.setBarrier(true); + flowBuilder.setTableId(INGRESS_ACL); + flowBuilder.setKey(key); + flowBuilder.setFlowName(flowId); + flowBuilder.setHardTimeout(0); + flowBuilder.setIdleTimeout(0); + + if (write) { + // Instantiate the Builders for the OF Actions and Instructions + InstructionBuilder ib = new InstructionBuilder(); + InstructionsBuilder isb = new InstructionsBuilder(); + List instructionsList = Lists.newArrayList(); + + ib = this.getMutablePipelineInstructionBuilder(); + ib.setOrder(1); + ib.setKey(new InstructionKey(1)); + instructionsList.add(ib.build()); + isb.setInstruction(instructionsList); + logger.debug("Instructions contain: {}", ib.getInstruction()); + + // Add InstructionsBuilder to FlowBuilder + flowBuilder.setInstructions(isb.build()); + writeFlow(flowBuilder, nodeBuilder); + } else { + // removeFlow(flowBuilder, nodeBuilder); + } + } + + + public void ingressACLDefaultTcpDrop(Long dpidLong, String segmentationId, String attachedMac, + int priority, boolean write) { + + String nodeName = OPENFLOW + dpidLong; + MatchBuilder matchBuilder = new MatchBuilder(); + NodeBuilder nodeBuilder = createNodeBuilder(nodeName); + FlowBuilder flowBuilder = new FlowBuilder(); + + flowBuilder.setMatch(MatchUtils.createDmacTcpPortWithFlagMatch(matchBuilder, + attachedMac, TCP_SYN, segmentationId).build()); + + logger.debug("MatchBuilder contains: {}", flowBuilder.getMatch()); + String flowId = "PortSec_TCP_Syn_Default_Drop_" + attachedMac; + flowBuilder.setId(new FlowId(flowId)); + FlowKey key = new FlowKey(new FlowId(flowId)); + flowBuilder.setStrict(false); + flowBuilder.setPriority(priority); + flowBuilder.setBarrier(true); + flowBuilder.setTableId(INGRESS_ACL); + flowBuilder.setKey(key); + flowBuilder.setFlowName(flowId); + flowBuilder.setHardTimeout(0); + flowBuilder.setIdleTimeout(0); + + if (write) { + // Instantiate the Builders for the OF Actions and Instructions + InstructionBuilder ib = new InstructionBuilder(); + InstructionsBuilder isb = new InstructionsBuilder(); + + // Instructions List Stores Individual Instructions + List instructions = Lists.newArrayList(); + + // Set the Output Port/Iface + InstructionUtils.createDropInstructions(ib); + ib.setOrder(0); + ib.setKey(new InstructionKey(0)); + instructions.add(ib.build()); + + // Add InstructionBuilder to the Instruction(s)Builder List + isb.setInstruction(instructions); + logger.debug("Instructions contain: {}", ib.getInstruction()); + // Add InstructionsBuilder to FlowBuilder + flowBuilder.setInstructions(isb.build()); + writeFlow(flowBuilder, nodeBuilder); + } else { + // removeFlow(flowBuilder, nodeBuilder); + } + } + + public void ingressACLPermitAllProto(Long dpidLong, String segmentationId, String attachedMac, + boolean write, String securityRuleIpPrefix, Integer protoPortMatchPriority) { + + String nodeName = OPENFLOW + dpidLong; + Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix); + MatchBuilder matchBuilder = new MatchBuilder(); + NodeBuilder nodeBuilder = createNodeBuilder(nodeName); + FlowBuilder flowBuilder = new FlowBuilder(); + + flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)) + .build()); + if (securityRuleIpPrefix != null) { + flowBuilder.setMatch(MatchUtils + .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, srcIpPrefix) + .build()); + } else { + flowBuilder.setMatch(MatchUtils + .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null) + .build()); + } + + logger.debug("MatchBuilder contains: {}", flowBuilder.getMatch()); + String flowId = "IngressProto_ACL_" + segmentationId + "_" + + attachedMac + "_Permit_" + securityRuleIpPrefix; + // Add Flow Attributes + flowBuilder.setId(new FlowId(flowId)); + FlowKey key = new FlowKey(new FlowId(flowId)); + flowBuilder.setStrict(false); + flowBuilder.setPriority(protoPortMatchPriority); + flowBuilder.setBarrier(true); + flowBuilder.setTableId(INGRESS_ACL); + flowBuilder.setKey(key); + flowBuilder.setFlowName(flowId); + flowBuilder.setHardTimeout(0); + flowBuilder.setIdleTimeout(0); + + if (write) { + // Instantiate the Builders for the OF Actions and Instructions + InstructionBuilder ib = new InstructionBuilder(); + InstructionsBuilder isb = new InstructionsBuilder(); + List instructionsList = Lists.newArrayList(); + + ib = this.getMutablePipelineInstructionBuilder(); + ib.setOrder(1); + ib.setKey(new InstructionKey(0)); + instructionsList.add(ib.build()); + isb.setInstruction(instructionsList); + + logger.debug("Instructions contain: {}", ib.getInstruction()); + // Add InstructionsBuilder to FlowBuilder + flowBuilder.setInstructions(isb.build()); + writeFlow(flowBuilder, nodeBuilder); + } else { + // // removeFlow(flowBuilder, nodeBuilder); + } + } + + public void egressACLDefaultTcpDrop(Long dpidLong, String segmentationId, String attachedMac, + int priority, boolean write) { + + String nodeName = OPENFLOW + dpidLong; + MatchBuilder matchBuilder = new MatchBuilder(); + NodeBuilder nodeBuilder = createNodeBuilder(nodeName); + FlowBuilder flowBuilder = new FlowBuilder(); + + flowBuilder.setMatch(MatchUtils.createSmacTcpPortWithFlagMatch(matchBuilder, + attachedMac, TCP_SYN, segmentationId).build()); + logger.debug("MatchBuilder contains: {}", flowBuilder.getMatch()); + + String flowId = "TCP_Syn_Egress_Default_Drop_" + attachedMac; + flowBuilder.setId(new FlowId(flowId)); + FlowKey key = new FlowKey(new FlowId(flowId)); + flowBuilder.setStrict(false); + flowBuilder.setPriority(priority); + flowBuilder.setBarrier(true); + flowBuilder.setTableId(EGRESS_ACL); + flowBuilder.setKey(key); + flowBuilder.setFlowName(flowId); + flowBuilder.setHardTimeout(0); + flowBuilder.setIdleTimeout(0); + + if (write) { + // Instantiate the Builders for the OF Actions and Instructions + InstructionBuilder ib = new InstructionBuilder(); + InstructionsBuilder isb = new InstructionsBuilder(); + List instructions = Lists.newArrayList(); + + InstructionUtils.createDropInstructions(ib); + ib.setOrder(0); + ib.setKey(new InstructionKey(0)); + instructions.add(ib.build()); + // Add InstructionBuilder to the Instruction(s)Builder List + isb.setInstruction(instructions); + + logger.debug("Instructions contain: {}", ib.getInstruction()); + // Add InstructionsBuilder to FlowBuilder + flowBuilder.setInstructions(isb.build()); + writeFlow(flowBuilder, nodeBuilder); + } else { + // TODO Add // removeFlow to AnstractServiceInstance + //// removeFlow(flowBuilder, nodeBuilder); + } + } + + public void egressACLTcpPortWithPrefix(Long dpidLong, String segmentationId, String attachedMac, boolean write, + Integer securityRulePortMin, String securityRuleIpPrefix, Integer protoPortPrefixMatchPriority) { + + String nodeName = OPENFLOW + dpidLong; + PortNumber tcpPort = new PortNumber(securityRulePortMin); + MatchBuilder matchBuilder = new MatchBuilder(); + NodeBuilder nodeBuilder = createNodeBuilder(nodeName); + FlowBuilder flowBuilder = new FlowBuilder(); + Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix); + + flowBuilder.setMatch(MatchUtils + .createSmacTcpSynDstIpPrefixTcpPort(matchBuilder, new MacAddress(attachedMac), + tcpPort, TCP_SYN, segmentationId, srcIpPrefix).build()); + + logger.debug(" MatchBuilder contains: {}", flowBuilder.getMatch()); + String flowId = "UcastEgress_" + segmentationId + "_" + attachedMac + + securityRulePortMin + securityRuleIpPrefix; + // Add Flow Attributes + flowBuilder.setId(new FlowId(flowId)); + FlowKey key = new FlowKey(new FlowId(flowId)); + flowBuilder.setStrict(false); + flowBuilder.setPriority(protoPortPrefixMatchPriority); + flowBuilder.setBarrier(true); + flowBuilder.setTableId(EGRESS_ACL); + flowBuilder.setKey(key); + flowBuilder.setFlowName(flowId); + flowBuilder.setHardTimeout(0); + flowBuilder.setIdleTimeout(0); + + if (write) { + // Instantiate the Builders for the OF Actions and Instructions + InstructionBuilder ib = new InstructionBuilder(); + InstructionsBuilder isb = new InstructionsBuilder(); + List instructionsList = Lists.newArrayList(); + + InstructionUtils.createGotoTableInstructions(ib, OUTBOUND_SNAT); + ib.setOrder(0); + ib.setKey(new InstructionKey(0)); + instructionsList.add(ib.build()); + isb.setInstruction(instructionsList); + + logger.debug("Instructions contain: {}", ib.getInstruction()); + // Add InstructionsBuilder to FlowBuilder + flowBuilder.setInstructions(isb.build()); + writeFlow(flowBuilder, nodeBuilder); + } else { + // TODO Add // removeFlow to AnstractServiceInstance + //// removeFlow(flowBuilder, nodeBuilder); + } + } + + + + public void egressAllowProto(Long dpidLong, String segmentationId, String attachedMac, boolean write, + String securityRuleProtcol, Integer protoMatchPriority) { + + String nodeName = OPENFLOW + dpidLong; + MatchBuilder matchBuilder = new MatchBuilder(); + NodeBuilder nodeBuilder = createNodeBuilder(nodeName); + FlowBuilder flowBuilder = new FlowBuilder(); + + flowBuilder.setMatch(MatchUtils + .createDmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null).build()); + flowBuilder.setMatch(MatchUtils + .createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build()); + + logger.debug("MatchBuilder contains: {}", flowBuilder.getMatch()); + String flowId = "EgressAllProto_" + segmentationId + "_" + + attachedMac + "_AllowEgressTCPSyn_" + securityRuleProtcol; + // Add Flow Attributes + flowBuilder.setId(new FlowId(flowId)); + FlowKey key = new FlowKey(new FlowId(flowId)); + flowBuilder.setStrict(false); + flowBuilder.setPriority(protoMatchPriority); + flowBuilder.setBarrier(true); + flowBuilder.setTableId(EGRESS_ACL); + flowBuilder.setKey(key); + flowBuilder.setFlowName(flowId); + flowBuilder.setHardTimeout(0); + flowBuilder.setIdleTimeout(0); + + if (write) { + // Instantiate the Builders for the OF Actions and Instructions + InstructionBuilder ib = new InstructionBuilder(); + InstructionsBuilder isb = new InstructionsBuilder(); + List instructionsList = Lists.newArrayList(); + + InstructionUtils.createGotoTableInstructions(ib, OUTBOUND_SNAT); + ib.setOrder(0); + ib.setKey(new InstructionKey(0)); + instructionsList.add(ib.build()); + isb.setInstruction(instructionsList); + + logger.debug("Instructions contain: {}", ib.getInstruction()); + // Add InstructionsBuilder to FlowBuilder + flowBuilder.setInstructions(isb.build()); + writeFlow(flowBuilder, nodeBuilder); + } else { + // removeFlow(flowBuilder, nodeBuilder); + } + } + + public void egressACLPermitAllProto(Long dpidLong, String segmentationId, String attachedMac, + boolean write, String securityRuleIpPrefix, Integer protoPortMatchPriority) { + + String nodeName = OPENFLOW + dpidLong; + Ipv4Prefix srcIpPrefix = new Ipv4Prefix(securityRuleIpPrefix); + MatchBuilder matchBuilder = new MatchBuilder(); + NodeBuilder nodeBuilder = createNodeBuilder(nodeName); + FlowBuilder flowBuilder = new FlowBuilder(); + + flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)) + .build()); + if (securityRuleIpPrefix != null) { + flowBuilder.setMatch(MatchUtils + .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, srcIpPrefix) + .build()); + } else { + flowBuilder.setMatch(MatchUtils + .createSmacIpTcpSynMatch(matchBuilder, new MacAddress(attachedMac), null, null) + .build()); + } + logger.debug("MatchBuilder contains: {}", flowBuilder.getMatch()); + String flowId = "Egress_Proto_ACL" + segmentationId + "_" + + attachedMac + "_Permit_" + securityRuleIpPrefix; + // Add Flow Attributes + flowBuilder.setId(new FlowId(flowId)); + FlowKey key = new FlowKey(new FlowId(flowId)); + flowBuilder.setStrict(false); + flowBuilder.setPriority(protoPortMatchPriority); + flowBuilder.setBarrier(true); + flowBuilder.setTableId(EGRESS_ACL); + flowBuilder.setKey(key); + flowBuilder.setFlowName(flowId); + flowBuilder.setHardTimeout(0); + flowBuilder.setIdleTimeout(0); + + if (write) { + // Instantiate the Builders for the OF Actions and Instructions + InstructionBuilder ib = new InstructionBuilder(); + InstructionsBuilder isb = new InstructionsBuilder(); + List instructionsList = Lists.newArrayList(); + + InstructionUtils.createGotoTableInstructions(ib, OUTBOUND_SNAT); + ib.setOrder(0); + ib.setKey(new InstructionKey(0)); + instructionsList.add(ib.build()); + isb.setInstruction(instructionsList); + + logger.debug("Instructions contain: {}", ib.getInstruction()); + // Add InstructionsBuilder to FlowBuilder + flowBuilder.setInstructions(isb.build()); + writeFlow(flowBuilder, nodeBuilder); + } else { + // removeFlow(flowBuilder, nodeBuilder); + } + } + + + public void egressACLTcpSyn(Long dpidLong, String segmentationId, String attachedMac, boolean write, + Integer securityRulePortMin, Integer protoPortMatchPriority) { + + String nodeName = OPENFLOW + dpidLong; + PortNumber tcpPort = new PortNumber(securityRulePortMin); + MatchBuilder matchBuilder = new MatchBuilder(); + NodeBuilder nodeBuilder = createNodeBuilder(nodeName); + FlowBuilder flowBuilder = new FlowBuilder(); + + flowBuilder.setMatch(MatchUtils.createSmacTcpSyn(matchBuilder, attachedMac, tcpPort, + TCP_SYN, segmentationId).build()); + + logger.debug("MatchBuilder contains: {}", flowBuilder.getMatch()); + String flowId = "Ucast_Egress_ACL" + segmentationId + "_" + attachedMac + securityRulePortMin; + // Add Flow Attributes + flowBuilder.setId(new FlowId(flowId)); + FlowKey key = new FlowKey(new FlowId(flowId)); + flowBuilder.setStrict(false); + flowBuilder.setPriority(protoPortMatchPriority); + flowBuilder.setBarrier(true); + flowBuilder.setTableId(EGRESS_ACL); + flowBuilder.setKey(key); + flowBuilder.setFlowName(flowId); + flowBuilder.setHardTimeout(0); + flowBuilder.setIdleTimeout(0); + + if (write) { + // Instantiate the Builders for the OF Actions and Instructions + InstructionBuilder ib = new InstructionBuilder(); + InstructionsBuilder isb = new InstructionsBuilder(); + List instructionsList = Lists.newArrayList(); + + InstructionUtils.createGotoTableInstructions(ib, OUTBOUND_SNAT); + ib.setOrder(0); + ib.setKey(new InstructionKey(0)); + instructionsList.add(ib.build()); + isb.setInstruction(instructionsList); + + logger.debug("Instructions contain: {}", ib.getInstruction()); + // Add InstructionsBuilder to FlowBuilder + flowBuilder.setInstructions(isb.build()); + writeFlow(flowBuilder, nodeBuilder); + } else { + // removeFlow(flowBuilder, nodeBuilder); + } + } +} diff --git a/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/Activator.java b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/Activator.java index 907aeaa32..5e38d1507 100644 --- a/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/Activator.java +++ b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/Activator.java @@ -42,6 +42,7 @@ import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProvider; import org.opendaylight.ovsdb.openstack.netvirt.api.NetworkingProviderManager; import org.opendaylight.ovsdb.openstack.netvirt.api.OutboundNatProvider; import org.opendaylight.ovsdb.openstack.netvirt.api.RoutingProvider; +import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager; import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager; import org.opendaylight.ovsdb.openstack.netvirt.api.VlanConfigurationCache; import org.opendaylight.ovsdb.openstack.netvirt.impl.BridgeConfigurationManagerImpl; @@ -50,6 +51,7 @@ import org.opendaylight.ovsdb.openstack.netvirt.impl.EventDispatcherImpl; import org.opendaylight.ovsdb.openstack.netvirt.impl.NeutronL3Adapter; import org.opendaylight.ovsdb.openstack.netvirt.impl.OpenstackRouter; import org.opendaylight.ovsdb.openstack.netvirt.impl.ProviderNetworkManagerImpl; +import org.opendaylight.ovsdb.openstack.netvirt.impl.SecurityServicesImpl; import org.opendaylight.ovsdb.openstack.netvirt.impl.TenantNetworkManagerImpl; import org.opendaylight.ovsdb.openstack.netvirt.impl.VlanConfigurationCacheImpl; import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService; @@ -108,7 +110,8 @@ public class Activator extends ComponentActivatorAbstractBase { LBaaSHandler.class, LBaaSPoolMemberHandler.class, NeutronL3Adapter.class, - OpenstackRouter.class}; + OpenstackRouter.class, + SecurityServicesImpl.class}; return res; } @@ -275,11 +278,16 @@ public class Activator extends ComponentActivatorAbstractBase { Properties portSecurityHandlerProperties = new Properties(); portSecurityHandlerProperties.put(Constants.EVENT_HANDLER_TYPE_PROPERTY, AbstractEvent.HandlerType.NEUTRON_PORT_SECURITY); - c.setInterface(new String[] {INeutronSecurityRuleAware.class.getName(), - INeutronSecurityGroupAware.class.getName(), - AbstractHandler.class.getName()}, + c.setInterface(new String[]{INeutronSecurityRuleAware.class.getName(), + INeutronSecurityGroupAware.class.getName(), + AbstractHandler.class.getName()}, portSecurityHandlerProperties); c.add(createServiceDependency().setService(EventDispatcher.class).setRequired(true)); + c.add(createServiceDependency().setService(SecurityServicesManager.class).setRequired(true)); + } + + if (imp.equals(SecurityServicesImpl.class)) { + c.setInterface(new String[] {SecurityServicesManager.class.getName()}, null); } if (imp.equals(FWaasHandler.class)) { diff --git a/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/IngressAclProvider.java b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/IngressAclProvider.java new file mode 100644 index 000000000..f61cc1e0e --- /dev/null +++ b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/IngressAclProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + */ + +package org.opendaylight.ovsdb.openstack.netvirt.api; + +import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup; +import org.opendaylight.controller.sal.core.Node; + +/** + * This interface allows Port Security flows to be written to devices + */ +public interface IngressAclProvider { + + /** + * Program port security ACL. + * + * @param node the node + * @param dpid the dpid + * @param segmentationId the segmentation id + * @param attachedMac the attached mac + * @param localPort the local port + * @param securityGroup the security group + */ + public void programPortSecurityACL(Node node, Long dpid, String segmentationId, String attachedMac, + long localPort, NeutronSecurityGroup securityGroup); +} diff --git a/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/SecurityServicesManager.java b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/SecurityServicesManager.java new file mode 100644 index 000000000..7904dbf37 --- /dev/null +++ b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/api/SecurityServicesManager.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + */ + +package org.opendaylight.ovsdb.openstack.netvirt.api; + +import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup; +import org.opendaylight.ovsdb.schema.openvswitch.Interface; + +/** + * Open vSwitch isolates Tenant Networks using VLANs on the Integration Bridge + * This class manages the provisioning of these VLANs + */ +public interface SecurityServicesManager { + /** + * Is port security ready. + * + * @param intf the intf + * @return the boolean + */ + public boolean isPortSecurityReady(Interface intf); + /** + * Gets security group in port. + * + * @param intf the intf + * @return the security group in port + */ + public NeutronSecurityGroup getSecurityGroupInPort(Interface intf); + +} \ No newline at end of file diff --git a/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/SecurityServicesImpl.java b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/SecurityServicesImpl.java new file mode 100644 index 000000000..cf912dc45 --- /dev/null +++ b/openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/SecurityServicesImpl.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.ovsdb.openstack.netvirt.impl; + +import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronPort; +import org.opendaylight.controller.networkconfig.neutron.NeutronSecurityGroup; +import org.opendaylight.controller.sal.utils.ServiceHelper; +import org.opendaylight.ovsdb.openstack.netvirt.api.Constants; +import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager; + +import org.opendaylight.ovsdb.schema.openvswitch.Interface; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; + +public class SecurityServicesImpl implements SecurityServicesManager { + + static final Logger logger = LoggerFactory.getLogger(TenantNetworkManagerImpl.class); + + public SecurityServicesImpl() { + } + + /** + * Is security group ready. + * + * @param intf the intf + * @return the boolean + */ + public boolean isPortSecurityReady(Interface intf) { + logger.trace("getTenantNetworkForInterface for {}", intf); + if (intf == null) return false; + Map externalIds = intf.getExternalIdsColumn().getData(); + logger.trace("externalIds {}", externalIds); + if (externalIds == null) return false; + String neutronPortId = externalIds.get(Constants.EXTERNAL_ID_INTERFACE_ID); + if (neutronPortId == null) return false; + INeutronPortCRUD neutronPortService = (INeutronPortCRUD) ServiceHelper.getGlobalInstance(INeutronPortCRUD.class, + this); + NeutronPort neutronPort = neutronPortService.getPort(neutronPortId); + String deviceOwner = neutronPort.getDeviceOwner(); + if (!deviceOwner.contains("compute")) { + logger.debug("Port {} is not a compute host, it is a: {}", neutronPortId, deviceOwner); + } + logger.debug("isPortSecurityReady() is a {} ", deviceOwner); + List securityGroups = neutronPort.getSecurityGroups(); + if (securityGroups.isEmpty()) { + logger.debug("Check for device: {} does not contain a Security Group for port: {}", deviceOwner, + neutronPortId); + return false; + } + try { + String vmPort = externalIds.get("attached-mac"); + } catch(Exception e) { + logger.debug("Error VMID did *NOT* work"); + } + logger.debug("Security Group Check {} DOES contain a Neutron Security Group", neutronPortId); + return true; + } + + /** + * Gets security group in port. + * + * @param intf the intf + * @return the security group in port + */ + public NeutronSecurityGroup getSecurityGroupInPort(Interface intf) { + logger.trace("getTenantNetworkForInterface for {}", intf); + if (intf == null) return null; + Map externalIds = intf.getExternalIdsColumn().getData(); + logger.trace("externalIds {}", externalIds); + if (externalIds == null) return null; + String neutronPortId = externalIds.get(Constants.EXTERNAL_ID_INTERFACE_ID); + if (neutronPortId == null) return null; + INeutronPortCRUD neutronPortService = (INeutronPortCRUD) + ServiceHelper.getGlobalInstance(INeutronPortCRUD.class, this); + NeutronPort neutronPort = neutronPortService.getPort(neutronPortId); + List neutronSecurityGroups = neutronPort.getSecurityGroups(); + NeutronSecurityGroup neutronSecurityGroup = (NeutronSecurityGroup) neutronSecurityGroups.toArray()[0]; + return neutronSecurityGroup; + } +} diff --git a/utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/MatchUtils.java b/utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/MatchUtils.java index 22f78f14c..8ad2aace1 100644 --- a/utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/MatchUtils.java +++ b/utils/mdsal-openflow/src/main/java/org/opendaylight/ovsdb/utils/mdsal/openflow/MatchUtils.java @@ -73,6 +73,12 @@ import com.google.common.collect.Lists; public class MatchUtils { private static final Logger logger = LoggerFactory.getLogger(MatchUtils.class); + public static final short ICMP_SHORT = 1; + public static final short TCP_SHORT = 6; + public static final short UDP_SHORT = 17; + public static final String TCP = "tcp"; + public static final String UDP = "udp"; + private static final int TCP_SYN = 0x0002; /** * Create Ingress Port Match dpidLong, inPort @@ -365,6 +371,473 @@ public class MatchUtils { return matchBuilder; } + /** + * Create TCP Port Match + * + * @param matchBuilder @param matchbuilder MatchBuilder Object without a match yet + * @param tcpport Integer representing a source TCP port + * @return matchBuilder Map MatchBuilder Object with a match + */ + public static MatchBuilder createIpProtocolMatch(MatchBuilder matchBuilder, short ipProtocol) { + + EthernetMatchBuilder ethType = new EthernetMatchBuilder(); + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x0800L)); + ethType.setEthernetType(ethTypeBuilder.build()); + matchBuilder.setEthernetMatch(ethType.build()); + + IpMatchBuilder ipMmatch = new IpMatchBuilder(); + if (ipProtocol == TCP_SHORT) { + ipMmatch.setIpProtocol(TCP_SHORT); + } + else if (ipProtocol == UDP_SHORT) { + ipMmatch.setIpProtocol(UDP_SHORT); + } + else if (ipProtocol == ICMP_SHORT) { + ipMmatch.setIpProtocol(ICMP_SHORT); + } + matchBuilder.setIpMatch(ipMmatch.build()); + return matchBuilder; + } + + /** + * Create tcp syn with proto match. + * + * @param matchBuilder the match builder + * @return matchBuilder match builder + */ + public static MatchBuilder createTcpSynWithProtoMatch(MatchBuilder matchBuilder) { + + // Ethertype match + EthernetMatchBuilder ethernetType = new EthernetMatchBuilder(); + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x0800L)); + ethernetType.setEthernetType(ethTypeBuilder.build()); + matchBuilder.setEthernetMatch(ethernetType.build()); + + // TCP Protocol Match + IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version + ipMatch.setIpProtocol((short) 6); + matchBuilder.setIpMatch(ipMatch.build()); + + TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder(); + tcpFlagMatch.setTcpFlag(TCP_SYN); + matchBuilder.setTcpFlagMatch(tcpFlagMatch.build()); + return matchBuilder; + } + + /** + * Create tcp proto syn match. + * + * @param matchBuilder the match builder + * @return matchBuilder match builder + */ + public static MatchBuilder createTcpProtoSynMatch(MatchBuilder matchBuilder) { + + // TCP Protocol Match + IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version + ipMatch.setIpProtocol((short) 6); + matchBuilder.setIpMatch(ipMatch.build()); + + TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder(); + tcpFlagMatch.setTcpFlag(TCP_SYN); + matchBuilder.setTcpFlagMatch(tcpFlagMatch.build()); + return matchBuilder; + } + + /** + * Create dmac tcp port with flag match. + * + * @param matchBuilder the match builder + * @param attachedMac the attached mac + * @param tcpFlag the tcp flag + * @param tunnelID the tunnel iD + * @return match containing TCP_Flag (), IP Protocol (TCP), TCP_Flag (SYN) + */ + public static MatchBuilder createDmacTcpPortWithFlagMatch(MatchBuilder matchBuilder, + String attachedMac, Integer tcpFlag, String tunnelID) { + + EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder(); + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x0800L)); + ethernetMatch.setEthernetType(ethTypeBuilder.build()); + + EthernetDestinationBuilder ethDestinationBuilder = new EthernetDestinationBuilder(); + ethDestinationBuilder.setAddress(new MacAddress(attachedMac)); + ethernetMatch.setEthernetDestination(ethDestinationBuilder.build()); + matchBuilder.setEthernetMatch(ethernetMatch.build()); + + // TCP Protocol Match + IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version + ipMatch.setIpProtocol(TCP_SHORT); + matchBuilder.setIpMatch(ipMatch.build()); + + TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder(); + tcpFlagMatch.setTcpFlag(tcpFlag); + matchBuilder.setTcpFlagMatch(tcpFlagMatch.build()); + + TunnelBuilder tunnelBuilder = new TunnelBuilder(); + tunnelBuilder.setTunnelId(new BigInteger(tunnelID)); + matchBuilder.setTunnel(tunnelBuilder.build()); + + return matchBuilder; + } + + /** + * Create dmac tcp syn match. + * + * @param matchBuilder the match builder + * @param attachedMac the attached mac + * @param tcpPort the tcp port + * @param tcpFlag the tcp flag + * @param tunnelID the tunnel iD + * @return the match builder + */ + public static MatchBuilder createDmacTcpSynMatch(MatchBuilder matchBuilder, + String attachedMac, PortNumber tcpPort, Integer tcpFlag, String tunnelID) { + + EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder(); + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x0800L)); + ethernetMatch.setEthernetType(ethTypeBuilder.build()); + + EthernetDestinationBuilder ethDestinationBuilder = new EthernetDestinationBuilder(); + ethDestinationBuilder.setAddress(new MacAddress(attachedMac)); + ethernetMatch.setEthernetDestination(ethDestinationBuilder.build()); + matchBuilder.setEthernetMatch(ethernetMatch.build()); + + // TCP Protocol Match + IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version + ipMatch.setIpProtocol((short) 6); + matchBuilder.setIpMatch(ipMatch.build()); + + // TCP Port Match + PortNumber dstPort = new PortNumber(tcpPort); + TcpMatchBuilder tcpMatch = new TcpMatchBuilder(); + tcpMatch.setTcpDestinationPort(dstPort); + matchBuilder.setLayer4Match(tcpMatch.build()); + + TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder(); + tcpFlagMatch.setTcpFlag(tcpFlag); + matchBuilder.setTcpFlagMatch(tcpFlagMatch.build()); + + TunnelBuilder tunnelBuilder = new TunnelBuilder(); + tunnelBuilder.setTunnelId(new BigInteger(tunnelID)); + matchBuilder.setTunnel(tunnelBuilder.build()); + + return matchBuilder; + } + + /** + * Create dmac tcp syn dst ip prefix tcp port. + * + * @param matchBuilder the match builder + * @param attachedMac the attached mac + * @param tcpPort the tcp port + * @param tcpFlag the tcp flag + * @param segmentationId the segmentation id + * @param dstIp the dst ip + * @return the match builder + */ + public static MatchBuilder createDmacTcpSynDstIpPrefixTcpPort(MatchBuilder matchBuilder, + MacAddress attachedMac, PortNumber tcpPort, Integer tcpFlag, String segmentationId, + Ipv4Prefix dstIp) { + + EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder(); + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x0800L)); + ethernetMatch.setEthernetType(ethTypeBuilder.build()); + + EthernetDestinationBuilder ethDestinationBuilder = new EthernetDestinationBuilder(); + ethDestinationBuilder.setAddress(new MacAddress(attachedMac)); + ethernetMatch.setEthernetDestination(ethDestinationBuilder.build()); + + matchBuilder.setEthernetMatch(ethernetMatch.build()); + + Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder(); + ipv4match.setIpv4Destination(dstIp); + matchBuilder.setLayer3Match(ipv4match.build()); + + // TCP Protocol Match + IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version + ipMatch.setIpProtocol(TCP_SHORT); + matchBuilder.setIpMatch(ipMatch.build()); + + // TCP Port Match + PortNumber dstPort = new PortNumber(tcpPort); + TcpMatchBuilder tcpMatch = new TcpMatchBuilder(); + tcpMatch.setTcpDestinationPort(dstPort); + matchBuilder.setLayer4Match(tcpMatch.build()); + + TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder(); + tcpFlagMatch.setTcpFlag(tcpFlag); + matchBuilder.setTcpFlagMatch(tcpFlagMatch.build()); + + TunnelBuilder tunnelBuilder = new TunnelBuilder(); + tunnelBuilder.setTunnelId(new BigInteger(segmentationId)); + matchBuilder.setTunnel(tunnelBuilder.build()); + + return matchBuilder; + } + + /** + * Create dmac ip tcp syn match. + * + * @param matchBuilder the match builder + * @param dMacAddr the d mac addr + * @param mask the mask + * @param ipPrefix the ip prefix + * @return MatchBuilder containing the metadata match values + */ + public static MatchBuilder createDmacIpTcpSynMatch(MatchBuilder matchBuilder, + MacAddress dMacAddr, MacAddress mask, Ipv4Prefix ipPrefix) { + + EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder(); + EthernetDestinationBuilder ethDestBuilder = new EthernetDestinationBuilder(); + ethDestBuilder.setAddress(new MacAddress(dMacAddr)); + if (mask != null) { + ethDestBuilder.setMask(mask); + } + ethernetMatch.setEthernetDestination(ethDestBuilder.build()); + matchBuilder.setEthernetMatch(ethernetMatch.build()); + // Ethertype match + EthernetMatchBuilder ethernetType = new EthernetMatchBuilder(); + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x0800L)); + ethernetType.setEthernetType(ethTypeBuilder.build()); + matchBuilder.setEthernetMatch(ethernetType.build()); + if (ipPrefix != null) { + Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder(); + ipv4match.setIpv4Destination(ipPrefix); + matchBuilder.setLayer3Match(ipv4match.build()); + } + // TCP Protocol Match + IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version + ipMatch.setIpProtocol(TCP_SHORT); + matchBuilder.setIpMatch(ipMatch.build()); + // TCP Flag Match + TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder(); + tcpFlagMatch.setTcpFlag(TCP_SYN); + matchBuilder.setTcpFlagMatch(tcpFlagMatch.build()); + + return matchBuilder; + } + + /** + * Create smac tcp syn dst ip prefix tcp port. + * + * @param matchBuilder the match builder + * @param attachedMac the attached mac + * @param tcpPort the tcp port + * @param tcpFlag the tcp flag + * @param segmentationId the segmentation id + * @param dstIp the dst ip + * @return the match builder + */ + public static MatchBuilder createSmacTcpSynDstIpPrefixTcpPort(MatchBuilder matchBuilder, MacAddress attachedMac, + PortNumber tcpPort, Integer tcpFlag, String segmentationId, Ipv4Prefix dstIp) { + + EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder(); + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x0800L)); + ethernetMatch.setEthernetType(ethTypeBuilder.build()); + + EthernetSourceBuilder ethSourceBuilder = new EthernetSourceBuilder(); + ethSourceBuilder.setAddress(new MacAddress(attachedMac)); + ethernetMatch.setEthernetSource(ethSourceBuilder.build()); + + matchBuilder.setEthernetMatch(ethernetMatch.build()); + + Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder(); + ipv4match.setIpv4Destination(dstIp); + matchBuilder.setLayer3Match(ipv4match.build()); + + // TCP Protocol Match + IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version + ipMatch.setIpProtocol(TCP_SHORT); + matchBuilder.setIpMatch(ipMatch.build()); + + // TCP Port Match + PortNumber dstPort = new PortNumber(tcpPort); + TcpMatchBuilder tcpMatch = new TcpMatchBuilder(); + tcpMatch.setTcpDestinationPort(dstPort); + matchBuilder.setLayer4Match(tcpMatch.build()); + + TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder(); + tcpFlagMatch.setTcpFlag(tcpFlag); + matchBuilder.setTcpFlagMatch(tcpFlagMatch.build()); + + TunnelBuilder tunnelBuilder = new TunnelBuilder(); + tunnelBuilder.setTunnelId(new BigInteger(segmentationId)); + matchBuilder.setTunnel(tunnelBuilder.build()); + + return matchBuilder; + } + + /** + * Create smac tcp port with flag match. + * + * @param matchBuilder the match builder + * @param attachedMac the attached mac + * @param tcpFlag the tcp flag + * @param tunnelID the tunnel iD + * @return matchBuilder + */ + public static MatchBuilder createSmacTcpPortWithFlagMatch(MatchBuilder matchBuilder, String attachedMac, + Integer tcpFlag, String tunnelID) { + + EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder(); + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x0800L)); + ethernetMatch.setEthernetType(ethTypeBuilder.build()); + + EthernetSourceBuilder ethSrcBuilder = new EthernetSourceBuilder(); + ethSrcBuilder.setAddress(new MacAddress(attachedMac)); + ethernetMatch.setEthernetSource(ethSrcBuilder.build()); + matchBuilder.setEthernetMatch(ethernetMatch.build()); + + // TCP Protocol Match + IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version + ipMatch.setIpProtocol(TCP_SHORT); + matchBuilder.setIpMatch(ipMatch.build()); + + TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder(); + tcpFlagMatch.setTcpFlag(tcpFlag); + matchBuilder.setTcpFlagMatch(tcpFlagMatch.build()); + + TunnelBuilder tunnelBuilder = new TunnelBuilder(); + tunnelBuilder.setTunnelId(new BigInteger(tunnelID)); + matchBuilder.setTunnel(tunnelBuilder.build()); + + return matchBuilder; + } + + /** + * Create smac ip tcp syn match. + * + * @param matchBuilder the match builder + * @param dMacAddr the d mac addr + * @param mask the mask + * @param ipPrefix the ip prefix + * @return MatchBuilder containing the metadata match values + */ + public static MatchBuilder createSmacIpTcpSynMatch(MatchBuilder matchBuilder, MacAddress dMacAddr, + MacAddress mask, Ipv4Prefix ipPrefix) { + + EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder(); + EthernetSourceBuilder ethSrcBuilder = new EthernetSourceBuilder(); + ethSrcBuilder.setAddress(new MacAddress(dMacAddr)); + if (mask != null) { + ethSrcBuilder.setMask(mask); + } + ethernetMatch.setEthernetSource(ethSrcBuilder.build()); + matchBuilder.setEthernetMatch(ethernetMatch.build()); + // Ethertype match + EthernetMatchBuilder ethernetType = new EthernetMatchBuilder(); + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x0800L)); + ethernetType.setEthernetType(ethTypeBuilder.build()); + matchBuilder.setEthernetMatch(ethernetType.build()); + if (ipPrefix != null) { + Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder(); + ipv4match.setIpv4Destination(ipPrefix); + matchBuilder.setLayer3Match(ipv4match.build()); + } + // TCP Protocol Match + IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version + ipMatch.setIpProtocol(TCP_SHORT); + matchBuilder.setIpMatch(ipMatch.build()); + // TCP Flag Match + TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder(); + tcpFlagMatch.setTcpFlag(TCP_SYN); + matchBuilder.setTcpFlagMatch(tcpFlagMatch.build()); + + return matchBuilder; + } + + /** + * Create smac tcp syn. + * + * @param matchBuilder the match builder + * @param attachedMac the attached mac + * @param tcpPort the tcp port + * @param tcpFlag the tcp flag + * @param tunnelID the tunnel iD + * @return the match builder + */ + public static MatchBuilder createSmacTcpSyn(MatchBuilder matchBuilder, + String attachedMac, PortNumber tcpPort, Integer tcpFlag, String tunnelID) { + + EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder(); + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x0800L)); + ethernetMatch.setEthernetType(ethTypeBuilder.build()); + + EthernetSourceBuilder ethSrcBuilder = new EthernetSourceBuilder(); + ethSrcBuilder.setAddress(new MacAddress(attachedMac)); + ethernetMatch.setEthernetSource(ethSrcBuilder.build()); + matchBuilder.setEthernetMatch(ethernetMatch.build()); + + // TCP Protocol Match + IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version + ipMatch.setIpProtocol((short) 6); + matchBuilder.setIpMatch(ipMatch.build()); + + // TCP Port Match + PortNumber dstPort = new PortNumber(tcpPort); + TcpMatchBuilder tcpMatch = new TcpMatchBuilder(); + tcpMatch.setTcpDestinationPort(dstPort); + matchBuilder.setLayer4Match(tcpMatch.build()); + + + TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder(); + tcpFlagMatch.setTcpFlag(tcpFlag); + matchBuilder.setTcpFlagMatch(tcpFlagMatch.build()); + + TunnelBuilder tunnelBuilder = new TunnelBuilder(); + tunnelBuilder.setTunnelId(new BigInteger(tunnelID)); + matchBuilder.setTunnel(tunnelBuilder.build()); + + return matchBuilder; + } + + /** + * @return MatchBuilder containing the metadata match values + */ + public static MatchBuilder createMacSrcIpTcpSynMatch(MatchBuilder matchBuilder, + MacAddress dMacAddr, MacAddress mask, Ipv4Prefix ipPrefix) { + + EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder(); + EthernetDestinationBuilder ethDestinationBuilder = new EthernetDestinationBuilder(); + ethDestinationBuilder.setAddress(new MacAddress(dMacAddr)); + if (mask != null) { + ethDestinationBuilder.setMask(mask); + } + ethernetMatch.setEthernetDestination(ethDestinationBuilder.build()); + matchBuilder.setEthernetMatch(ethernetMatch.build()); + // Ethertype match + EthernetMatchBuilder ethernetType = new EthernetMatchBuilder(); + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x0800L)); + ethernetType.setEthernetType(ethTypeBuilder.build()); + matchBuilder.setEthernetMatch(ethernetType.build()); + if (ipPrefix != null) { + Ipv4MatchBuilder ipv4match = new Ipv4MatchBuilder(); + ipv4match.setIpv4Source(ipPrefix); + matchBuilder.setLayer3Match(ipv4match.build()); + } + // TCP Protocol Match + IpMatchBuilder ipMatch = new IpMatchBuilder(); // ipv4 version + ipMatch.setIpProtocol(TCP_SHORT); + matchBuilder.setIpMatch(ipMatch.build()); + // TCP Flag Match + TcpFlagMatchBuilder tcpFlagMatch = new TcpFlagMatchBuilder(); + tcpFlagMatch.setTcpFlag(TCP_SYN); + matchBuilder.setTcpFlagMatch(tcpFlagMatch.build()); + + return matchBuilder; + } + public static class RegMatch { final Class reg; final Long value; -- 2.36.6