From: sridhargaddam Date: Mon, 11 Jan 2016 16:10:49 +0000 (+0530) Subject: IPv6 support in Security Groups. X-Git-Tag: release/boron~507^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=dad76ed7d987962f1738dba3fd23dd66ca715b98;p=netvirt.git IPv6 support in Security Groups. This patch implements IPv6 support for Security Groups in OVSDB Net-virt. Pending: Test cases will be added in a subsequent patch. Change-Id: If692c9b205af87517d69cbcc9f8c1be4decc917e Signed-off-by: Sridhar Gaddam --- diff --git a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/EgressAclService.java b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/EgressAclService.java index a3f1d0f5c0..07aeb7df50 100644 --- a/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/EgressAclService.java +++ b/openstack/net-virt-providers/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/providers/openflow13/services/EgressAclService.java @@ -28,6 +28,7 @@ import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefixBuilder; 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.Ipv6Prefix; 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.action.types.rev131112.action.list.Action; @@ -69,7 +70,10 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA private volatile SecurityGroupCacheManger securityGroupCacheManger; private static final int DHCP_SOURCE_PORT = 67; private static final int DHCP_DESTINATION_PORT = 68; + private static final int DHCPV6_SOURCE_PORT = 547; + private static final int DHCPV6_DESTINATION_PORT = 546; private static final String HOST_MASK = "/32"; + private static final String V6_HOST_MASK = "/128"; private static final int PORT_RANGE_MIN = 1; private static final int PORT_RANGE_MAX = 65535; @@ -109,9 +113,8 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA continue; } - if ("IPv4".equals(portSecurityRule.getSecurityRuleEthertype()) - && portSecurityRule.getSecurityRuleDirection().equals("egress")) { - LOG.debug("programPortSecurityGroup: Acl Rule matching IPv4 and ingress is: {} ", portSecurityRule); + if (portSecurityRule.getSecurityRuleDirection().equals("egress")) { + LOG.debug("programPortSecurityGroup: Acl Rule matching IP and ingress is: {} ", portSecurityRule); if (null != portSecurityRule.getSecurityRemoteGroupID()) { //Remote Security group is selected List remoteSrcAddressList = securityServicesManager @@ -148,38 +151,13 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA Neutron_IPs vmIp, boolean write) { if (null == portSecurityRule.getSecurityRuleProtocol()) { /* TODO Rework on the priority values */ - egressAclIPv4(dpid, segmentationId, attachedMac, + boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6"); + egressAclIP(dpid, isIpv6, segmentationId, attachedMac, write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY); } else { String ipaddress = null; if (null != vmIp) { ipaddress = vmIp.getIpAddress(); - try { - InetAddress address = InetAddress.getByName(ipaddress); - // TODO: remove this when ipv6 support is implemented - if (address instanceof Inet6Address) { - LOG.debug("Skipping ip address {}. IPv6 support is not yet implemented.", address); - return; - } - } catch (UnknownHostException e) { - LOG.warn("Invalid ip address {}", ipaddress, e); - return; - } - } - - if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) { - String prefixStr = portSecurityRule.getSecurityRuleRemoteIpPrefix(); - try { - IpPrefix ipPrefix = IpPrefixBuilder.getDefaultInstance(prefixStr); - // TODO: remove this when ipv6 support is implemented - if (ipPrefix.getIpv6Prefix() != null) { - LOG.debug("Skipping ip prefix {}. IPv6 support is not yet implemented.", ipPrefix); - return; - } - } catch (IllegalArgumentException e) { - LOG.warn("Invalid ip prefix {}", prefixStr, e); - return; - } } switch (portSecurityRule.getSecurityRuleProtocol()) { @@ -196,6 +174,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY); break; case MatchUtils.ICMP: + case MatchUtils.ICMPV6: LOG.debug("programPortSecurityRule: Rule matching ICMP", portSecurityRule); egressAclIcmp(dpid, segmentationId, attachedMac, portSecurityRule, ipaddress,write, @@ -217,7 +196,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA boolean write, Integer priority) { MatchBuilder matchBuilder = new MatchBuilder(); String flowId = "Egress_Other_" + segmentationId + "_" + srcMac + "_"; - matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null); + matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null); short proto = 0; try { @@ -251,6 +230,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA // If it is the only port in the bridge add the rule to allow any DHCP client traffic //if (isLastPortinBridge) { egressAclDhcpAllowClientTrafficFromVm(dpid, write, Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY); + egressAclDhcpv6AllowClientTrafficFromVm(dpid, write, Constants.PROTO_DHCP_CLIENT_TRAFFIC_MATCH_PRIORITY); // } if (isComputePort) { programArpRule(dpid, segmentationId, localPort, attachedMac, write); @@ -260,6 +240,8 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA // add rule to drop the DHCP server traffic originating from the vm. egressAclDhcpDropServerTrafficfromVm(dpid, localPort, write, Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP); + egressAclDhcpv6DropServerTrafficfromVm(dpid, localPort, write, + Constants.PROTO_DHCP_CLIENT_SPOOF_MATCH_PRIORITY_DROP); //Adds rule to check legitimate ip/mac pair for each packet from the vm for (Neutron_IPs srcAddress : srcAddressList) { try { @@ -268,9 +250,10 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA String addressWithPrefix = srcAddress.getIpAddress() + HOST_MASK; egressAclAllowTrafficFromVmIpMacPair(dpid, localPort, attachedMac, addressWithPrefix, Constants.PROTO_VM_IP_MAC_MATCH_PRIORITY,write); - } else { - LOG.debug("Skipping IPv6 address {}. IPv6 support is not yet implemented.", - srcAddress.getIpAddress()); + } else if (address instanceof Inet6Address) { + String addressWithPrefix = srcAddress.getIpAddress() + V6_HOST_MASK; + egressAclAllowTrafficFromVmIpV6MacPair(dpid, localPort, attachedMac, addressWithPrefix, + Constants.PROTO_VM_IP_MAC_MATCH_PRIORITY,write); } } catch(UnknownHostException e) { LOG.warn("Invalid IP address {}", srcAddress.getIpAddress()); @@ -321,7 +304,7 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA MatchBuilder matchBuilder = new MatchBuilder(); NodeBuilder nodeBuilder = createNodeBuilder(nodeName); String flowName = "Egress_Fixed_Conntrk_Untrk_" + segmentationId + "_" + localPort + "_"; - matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder, attachMac, null); + matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder, attachMac, null); matchBuilder = MatchUtils.addCtState(matchBuilder,0x00,0X80); FlowBuilder flowBuilder = new FlowBuilder(); flowBuilder.setMatch(matchBuilder.build()); @@ -409,19 +392,23 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA } /** - * Allows IPv4 packet egress from the src mac address. + * Allows IPv4/v6 packet egress from the src mac address. * @param dpidLong the dpid * @param segmentationId the segementation id * @param srcMac the src mac address * @param write add or remove * @param protoPortMatchPriority the protocol match priority. */ - private void egressAclIPv4(Long dpidLong, String segmentationId, String srcMac, + private void egressAclIP(Long dpidLong, boolean isIpv6, String segmentationId, String srcMac, boolean write, Integer protoPortMatchPriority ) { NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong); MatchBuilder matchBuilder = new MatchBuilder(); String flowId = "Egress_IP" + segmentationId + "_" + srcMac + "_Permit_"; - matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null); + if (isIpv6) { + matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null); + } else { + matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null); + } syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false); } @@ -443,7 +430,12 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA boolean portRange = false; MatchBuilder matchBuilder = new MatchBuilder(); String flowId = "Egress_TCP_" + segmentationId + "_" + srcMac + "_"; - matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null); + boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6"); + if (isIpv6) { + matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null); + } else { + matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null); + } /* Custom TCP Match */ if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) { @@ -463,13 +455,22 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA } if (null != dstAddress) { flowId = flowId + dstAddress; - matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null, - MatchUtils.iPv4PrefixFromIPv4Address(dstAddress)); - + if (isIpv6) { + matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null, + MatchUtils.iPv6PrefixFromIPv6Address(dstAddress)); + } else { + matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null, + MatchUtils.iPv4PrefixFromIPv4Address(dstAddress)); + } } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) { flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix(); - matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null, - new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix())); + if (isIpv6) { + matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null, + new Ipv6Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix())); + } else { + matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null, + new Ipv4Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix())); + } } NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong); if (portRange) { @@ -489,8 +490,20 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA } } + private void egressAclIcmp(Long dpidLong, String segmentationId, String srcMac, + NeutronSecurityRule portSecurityRule, String dstAddress, + boolean write, Integer protoPortMatchPriority) { + + boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6"); + if (isIpv6) { + egressAclIcmpV6(dpidLong, segmentationId, srcMac, portSecurityRule, dstAddress, write, protoPortMatchPriority); + } else { + egressAclIcmpV4(dpidLong, segmentationId, srcMac, portSecurityRule, dstAddress, write, protoPortMatchPriority); + } + } + /** - * Creates a egress match with src macaddress. If dest address is specified + * Creates a icmp egress match with src macaddress. If dest address is specified * destination specific match will be created. Otherwise a match with a * CIDR will be created. * @param dpidLong the dpid @@ -501,13 +514,13 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA * @param write add or delete * @param protoPortMatchPriority the protocol match priority */ - private void egressAclIcmp(Long dpidLong, String segmentationId, String srcMac, - NeutronSecurityRule portSecurityRule, String dstAddress, - boolean write, Integer protoPortMatchPriority) { + private void egressAclIcmpV4(Long dpidLong, String segmentationId, String srcMac, + NeutronSecurityRule portSecurityRule, String dstAddress, + boolean write, Integer protoPortMatchPriority) { MatchBuilder matchBuilder = new MatchBuilder(); String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_"; - matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null); + matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null); /*Custom ICMP Match */ if (portSecurityRule.getSecurityRulePortMin() != null && portSecurityRule.getSecurityRulePortMax() != null) { @@ -537,6 +550,53 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled()); } + /** + * Creates a icmpv6 egress match with src macaddress. If dest address is specified + * destination specific match will be created. Otherwise a match with a + * CIDR will be created. + * @param dpidLong the dpid + * @param segmentationId the segmentation id + * @param srcMac the source mac address. + * @param portSecurityRule the security rule in the SG + * @param dstAddress the source IP address + * @param write add or delete + * @param protoPortMatchPriority the protocol match priority + */ + private void egressAclIcmpV6(Long dpidLong, String segmentationId, String srcMac, + NeutronSecurityRule portSecurityRule, String dstAddress, + boolean write, Integer protoPortMatchPriority) { + + MatchBuilder matchBuilder = new MatchBuilder(); + String flowId = "Egress_ICMP_" + segmentationId + "_" + srcMac + "_"; + matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null); + + /*Custom ICMP Match */ + if (portSecurityRule.getSecurityRulePortMin() != null && + portSecurityRule.getSecurityRulePortMax() != null) { + flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_" + + portSecurityRule.getSecurityRulePortMax().shortValue() + "_"; + matchBuilder = MatchUtils.createICMPv6Match(matchBuilder, + portSecurityRule.getSecurityRulePortMin().shortValue(), + portSecurityRule.getSecurityRulePortMax().shortValue()); + } else { + /* All ICMP Match */ // We are getting from neutron NULL for both min and max + flowId = flowId + "all" + "_" ; + matchBuilder = MatchUtils.createICMPv6Match(matchBuilder, MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP); + } + if (null != dstAddress) { + flowId = flowId + dstAddress; + matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null, + MatchUtils.iPv6PrefixFromIPv6Address(dstAddress)); + } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) { + flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix(); + matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null, + new Ipv6Prefix(portSecurityRule.getSecurityRuleRemoteIpPrefix())); + } + flowId = flowId + "_Permit"; + NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong); + syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false); + } + /** * Creates a egress match with src macaddress. If dest address is specified * destination specific match will be created. Otherwise a match with a @@ -555,7 +615,12 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA boolean portRange = false; MatchBuilder matchBuilder = new MatchBuilder(); String flowId = "Egress_UDP_" + segmentationId + "_" + srcMac + "_"; - matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,srcMac,null); + boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6"); + if (isIpv6) { + matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,srcMac,null); + } else { + matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,srcMac,null); + } /* Custom UDP Match */ if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) { @@ -575,13 +640,24 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA } if (null != dstAddress) { flowId = flowId + dstAddress; - matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null, - MatchUtils.iPv4PrefixFromIPv4Address(dstAddress)); + if (isIpv6) { + matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder,null, + MatchUtils.iPv6PrefixFromIPv6Address(dstAddress)); + } else { + matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder,null, + MatchUtils.iPv4PrefixFromIPv4Address(dstAddress)); + } } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) { flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix(); - matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null, - new Ipv4Prefix(portSecurityRule - .getSecurityRuleRemoteIpPrefix())); + if (isIpv6) { + matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder, null, + new Ipv6Prefix(portSecurityRule + .getSecurityRuleRemoteIpPrefix())); + } else { + matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, null, + new Ipv4Prefix(portSecurityRule + .getSecurityRuleRemoteIpPrefix())); + } } NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong); if (portRange) { @@ -776,6 +852,22 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, false, false); } + /** + * Adds flow to allow any DHCP IPv6 client traffic. + * + * @param dpidLong the dpid + * @param write whether to write or delete the flow + * @param priority the priority + */ + private void egressAclDhcpv6AllowClientTrafficFromVm(Long dpidLong, + boolean write, Integer priority) { + NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong); + String flowName = "Egress_DHCPv6_Client" + "_Permit_"; + MatchBuilder matchBuilder = new MatchBuilder(); + MatchUtils.createDhcpv6Match(matchBuilder, DHCPV6_DESTINATION_PORT, DHCPV6_SOURCE_PORT); + syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, false, false); + } + /** * Adds rule to prevent DHCP spoofing by the vm attached to the port. * @@ -795,6 +887,25 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, true, false); } + /** + * Adds rule to prevent DHCPv6 spoofing by the vm attached to the port. + * + * @param dpidLong the dpid + * @param localPort the local port + * @param write is write or delete + * @param priority the priority + */ + private void egressAclDhcpv6DropServerTrafficfromVm(Long dpidLong, long localPort, + boolean write, Integer priority) { + + NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong); + String flowName = "Egress_DHCPv6_Server" + "_" + localPort + "_DROP_"; + MatchBuilder matchBuilder = new MatchBuilder(); + MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort); + MatchUtils.createDhcpv6Match(matchBuilder, DHCPV6_SOURCE_PORT, DHCPV6_DESTINATION_PORT); + syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, true, false); + } + /** * Adds rule to check legitimate ip/mac pair for each packet from the vm. * @@ -817,6 +928,28 @@ public class EgressAclService extends AbstractServiceInstance implements EgressA syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, false, false); } + /** + * Adds rule to check legitimate ip/mac pair for each packet from the vm. + * + * @param dpidLong the dpid + * @param localPort the local port + * @param srcIp the vm ip address + * @param attachedMac the vm mac address + * @param priority the priority + * @param write is write or delete + */ + private void egressAclAllowTrafficFromVmIpV6MacPair(Long dpidLong, long localPort, + String attachedMac, String srcIp, + Integer priority, boolean write) { + NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong); + String flowName = "Egress_Allow_VM_IPv6_MAC" + "_" + localPort + attachedMac + "_Permit_"; + MatchBuilder matchBuilder = new MatchBuilder(); + MatchUtils.createSrcL3Ipv6MatchWithMac(matchBuilder, new Ipv6Prefix(srcIp),new MacAddress(attachedMac)); + MatchUtils.createInPortMatch(matchBuilder, dpidLong, localPort); + LOG.debug("egressAclAllowTrafficFromVmIpMacPair: MatchBuilder contains: {}", matchBuilder); + syncFlow(flowName, nodeBuilder, matchBuilder, priority, write, false, false); + } + /** * Add or remove flow to the node. * 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 e5d0a4c7d7..c437cea877 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 @@ -28,6 +28,7 @@ import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefixBuilder; 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.Ipv6Prefix; 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.action.types.rev131112.action.list.Action; @@ -105,9 +106,8 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres continue; } - if ("IPv4".equals(portSecurityRule.getSecurityRuleEthertype()) - && "ingress".equals(portSecurityRule.getSecurityRuleDirection())) { - LOG.debug("programPortSecurityGroup: Rule matching IPv4 and ingress is: {} ", portSecurityRule); + if ("ingress".equals(portSecurityRule.getSecurityRuleDirection())) { + LOG.debug("programPortSecurityGroup: Rule matching IP and ingress is: {} ", portSecurityRule); if (null != portSecurityRule.getSecurityRemoteGroupID()) { //Remote Security group is selected List remoteSrcAddressList = securityServicesManager @@ -142,39 +142,14 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres long localPort, NeutronSecurityRule portSecurityRule, Neutron_IPs vmIp, boolean write) { if (null == portSecurityRule.getSecurityRuleProtocol()) { - ingressAclIPv4(dpid, segmentationId, attachedMac, - write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY); + boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6"); + ingressAclIP(dpid, isIpv6, segmentationId, attachedMac, + write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY); } else { String ipaddress = null; if (null != vmIp) { ipaddress = vmIp.getIpAddress(); - try { - InetAddress address = InetAddress.getByName(ipaddress); - // TODO: remove this when ipv6 support is implemented - if (address instanceof Inet6Address) { - LOG.debug("Skipping ip address {}. IPv6 support is not yet implemented.", address); - return; - } - } catch (UnknownHostException e) { - LOG.warn("Invalid ip address {}", ipaddress, e); - return; - } - } - - if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) { - String ipPrefixStr = portSecurityRule.getSecurityRuleRemoteIpPrefix(); - try { - IpPrefix ipPrefix = IpPrefixBuilder.getDefaultInstance(ipPrefixStr); - // TODO: remove this when ipv6 support is implemented - if (ipPrefix.getIpv6Prefix() != null) { - LOG.debug("Skipping ip prefix {}. IPv6 support is not yet implemented.", ipPrefix); - return; - } - } catch (IllegalArgumentException e) { - LOG.warn("Invalid ip prefix {}", ipPrefixStr, e); - return; - } - } + } switch (portSecurityRule.getSecurityRuleProtocol()) { case MatchUtils.TCP: @@ -188,6 +163,7 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY); break; case MatchUtils.ICMP: + case MatchUtils.ICMPV6: LOG.debug("programPortSecurityRule: Rule matching ICMP", portSecurityRule); ingressAclIcmp(dpid, segmentationId, attachedMac, portSecurityRule, ipaddress, write, Constants.PROTO_PORT_PREFIX_MATCH_PRIORITY); @@ -208,7 +184,7 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres MatchBuilder matchBuilder = new MatchBuilder(); String flowId = "Ingress_Other_" + segmentationId + "_" + dstMac + "_"; - matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac); + matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,dstMac); short proto = 0; try { Integer protocol = new Integer(portSecurityRule.getSecurityRuleProtocol()); @@ -240,6 +216,8 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres if (isLastPortinSubnet && isComputePort ) { ingressAclDhcpAllowServerTraffic(dpid, segmentationId,dhcpMacAddress, write,Constants.PROTO_DHCP_SERVER_MATCH_PRIORITY); + ingressAclDhcpv6AllowServerTraffic(dpid, segmentationId,dhcpMacAddress, + write,Constants.PROTO_DHCP_SERVER_MATCH_PRIORITY); } if (isComputePort) { if (securityServicesManager.isConntrackEnabled()) { @@ -289,7 +267,7 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres MatchBuilder matchBuilder = new MatchBuilder(); NodeBuilder nodeBuilder = createNodeBuilder(nodeName); String flowName = "Ingress_Fixed_Conntrk_Untrk_" + segmentationId + "_" + localPort + "_"; - matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,attachMac); + matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,attachMac); matchBuilder = MatchUtils.addCtState(matchBuilder,0x00, 0x80); FlowBuilder flowBuilder = new FlowBuilder(); flowBuilder.setMatch(matchBuilder.build()); @@ -327,7 +305,7 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres MatchBuilder matchBuilder = new MatchBuilder(); NodeBuilder nodeBuilder = createNodeBuilder(nodeName); String flowName = "Ingress_Fixed_Conntrk_TrkEst_" + segmentationId + "_" + localPort + "_"; - matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,attachMac); + matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,attachMac); matchBuilder = MatchUtils.addCtState(matchBuilder,0x82, 0x82); FlowBuilder flowBuilder = new FlowBuilder(); flowBuilder.setMatch(matchBuilder.build()); @@ -355,7 +333,7 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres MatchBuilder matchBuilder = new MatchBuilder(); NodeBuilder nodeBuilder = createNodeBuilder(nodeName); String flowName = "Ingress_Fixed_Conntrk_NewDrop_" + segmentationId + "_" + localPort + "_"; - matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,attachMac); + matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,attachMac); matchBuilder = MatchUtils.addCtState(matchBuilder,0x01, 0x01); FlowBuilder flowBuilder = new FlowBuilder(); flowBuilder.setMatch(matchBuilder.build()); @@ -387,22 +365,26 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres } /** - * Allows IPv4 packet ingress to the destination mac address. + * Allows an IPv4/v6 packet ingress to the destination mac address. * @param dpidLong the dpid * @param segmentationId the segementation id * @param dstMac the destination mac address * @param write add or remove * @param protoPortMatchPriority the protocol match priority. */ - private void ingressAclIPv4(Long dpidLong, String segmentationId, String dstMac, - boolean write, Integer protoPortMatchPriority ) { + private void ingressAclIP(Long dpidLong, boolean isIpv6, String segmentationId, String dstMac, + boolean write, Integer protoPortMatchPriority ) { NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong); MatchBuilder matchBuilder = new MatchBuilder(); String flowId = "Ingress_IP" + segmentationId + "_" + dstMac + "_Permit_"; - matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac); + if (isIpv6) { + matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,null,dstMac); + }else { + matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,dstMac); + } syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled()); - } + /** * Creates a ingress match to the dst macaddress. If src address is specified * source specific match will be created. Otherwise a match with a CIDR will @@ -421,7 +403,12 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres boolean portRange = false; MatchBuilder matchBuilder = new MatchBuilder(); String flowId = "Ingress_TCP_" + segmentationId + "_" + dstMac + "_"; - matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac); + boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6"); + if (isIpv6) { + matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,null,dstMac); + } else { + matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,dstMac); + } /* Custom TCP Match*/ if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) { @@ -441,14 +428,24 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres } if (null != srcAddress) { flowId = flowId + srcAddress; - matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, - MatchUtils.iPv4PrefixFromIPv4Address(srcAddress),null); - + if (isIpv6) { + matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder, + MatchUtils.iPv6PrefixFromIPv6Address(srcAddress),null); + } else { + matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, + MatchUtils.iPv4PrefixFromIPv4Address(srcAddress),null); + } } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) { flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix(); - matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, - new Ipv4Prefix(portSecurityRule - .getSecurityRuleRemoteIpPrefix()),null); + if (isIpv6) { + matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder, + new Ipv6Prefix(portSecurityRule + .getSecurityRuleRemoteIpPrefix()),null); + } else { + matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, + new Ipv4Prefix(portSecurityRule + .getSecurityRuleRemoteIpPrefix()),null); + } } NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong); if (portRange) { @@ -484,9 +481,14 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres NeutronSecurityRule portSecurityRule, String srcAddress, boolean write, Integer protoPortMatchPriority ) { boolean portRange = false; + boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6"); MatchBuilder matchBuilder = new MatchBuilder(); String flowId = "Ingress_UDP_" + segmentationId + "_" + dstMac + "_"; - matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac); + if (isIpv6) { + matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,null,dstMac); + }else { + matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,dstMac); + } /* Custom UDP Match */ if (portSecurityRule.getSecurityRulePortMin().equals(portSecurityRule.getSecurityRulePortMax())) { @@ -506,14 +508,24 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres } if (null != srcAddress) { flowId = flowId + srcAddress; - matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, - MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null); - + if (isIpv6) { + matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder, + MatchUtils.iPv6PrefixFromIPv6Address(srcAddress), null); + } else { + matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, + MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null); + } } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) { flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix(); - matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, - new Ipv4Prefix(portSecurityRule - .getSecurityRuleRemoteIpPrefix()),null); + if (isIpv6) { + matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder, + new Ipv6Prefix(portSecurityRule + .getSecurityRuleRemoteIpPrefix()),null); + } else { + matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, + new Ipv4Prefix(portSecurityRule + .getSecurityRuleRemoteIpPrefix()),null); + } } NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong); if (portRange) { @@ -533,8 +545,20 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres } } + private void ingressAclIcmp(Long dpidLong, String segmentationId, String dstMac, + NeutronSecurityRule portSecurityRule, String srcAddress, + boolean write, Integer protoPortMatchPriority) { + + boolean isIpv6 = portSecurityRule.getSecurityRuleEthertype().equals("IPv6"); + if (isIpv6) { + ingressAclIcmpV6(dpidLong, segmentationId, dstMac, portSecurityRule, srcAddress, write, protoPortMatchPriority); + } else { + ingressAclIcmpV4(dpidLong, segmentationId, dstMac, portSecurityRule, srcAddress, write, protoPortMatchPriority); + } + } + /** - * Creates a ingress match to the dst macaddress. If src address is specified + * Creates a ingress icmp match to the dst macaddress. If src address is specified * source specific match will be created. Otherwise a match with a CIDR will * be created. * @param dpidLong the dpid @@ -545,13 +569,13 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres * @param write add or delete * @param protoPortMatchPriority the protocol match priority */ - private void ingressAclIcmp(Long dpidLong, String segmentationId, String dstMac, - NeutronSecurityRule portSecurityRule, String srcAddress, - boolean write, Integer protoPortMatchPriority) { + private void ingressAclIcmpV4(Long dpidLong, String segmentationId, String dstMac, + NeutronSecurityRule portSecurityRule, String srcAddress, + boolean write, Integer protoPortMatchPriority) { MatchBuilder matchBuilder = new MatchBuilder(); String flowId = "Ingress_ICMP_" + segmentationId + "_" + dstMac + "_"; - matchBuilder = MatchUtils.createEtherMatchWithType(matchBuilder,null,dstMac); + matchBuilder = MatchUtils.createV4EtherMatchWithType(matchBuilder,null,dstMac); /* Custom ICMP Match */ if (portSecurityRule.getSecurityRulePortMin() != null && @@ -569,7 +593,7 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres if (null != srcAddress) { flowId = flowId + srcAddress; matchBuilder = MatchUtils.addRemoteIpPrefix(matchBuilder, - MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null); + MatchUtils.iPv4PrefixFromIPv4Address(srcAddress), null); } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) { flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix(); if (!portSecurityRule.getSecurityRuleRemoteIpPrefix().contains("/0")) { @@ -582,6 +606,54 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, securityServicesManager.isConntrackEnabled()); } + /** + * Creates a ingress icmpv6 match to the dst macaddress. If src address is specified + * source specific match will be created. Otherwise a match with a CIDR will + * be created. + * @param dpidLong the dpid + * @param segmentationId the segmentation id + * @param dstMac the destination mac address. + * @param portSecurityRule the security rule in the SG + * @param srcAddress the destination IP address + * @param write add or delete + * @param protoPortMatchPriority the protocol match priority + */ + private void ingressAclIcmpV6(Long dpidLong, String segmentationId, String dstMac, + NeutronSecurityRule portSecurityRule, String srcAddress, + boolean write, Integer protoPortMatchPriority) { + + MatchBuilder matchBuilder = new MatchBuilder(); + String flowId = "Ingress_ICMP_" + segmentationId + "_" + dstMac + "_"; + matchBuilder = MatchUtils.createV6EtherMatchWithType(matchBuilder,null,dstMac); + + /* Custom ICMP Match */ + if (portSecurityRule.getSecurityRulePortMin() != null && + portSecurityRule.getSecurityRulePortMax() != null) { + flowId = flowId + portSecurityRule.getSecurityRulePortMin().shortValue() + "_" + + portSecurityRule.getSecurityRulePortMax().shortValue() + "_"; + matchBuilder = MatchUtils.createICMPv6Match(matchBuilder, + portSecurityRule.getSecurityRulePortMin().shortValue(), + portSecurityRule.getSecurityRulePortMax().shortValue()); + } else { + /* All ICMP Match */ + flowId = flowId + "all" + "_"; + matchBuilder = MatchUtils.createICMPv6Match(matchBuilder,MatchUtils.ALL_ICMP, MatchUtils.ALL_ICMP); + } + if (null != srcAddress) { + flowId = flowId + srcAddress; + matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder, + MatchUtils.iPv6PrefixFromIPv6Address(srcAddress), null); + } else if (null != portSecurityRule.getSecurityRuleRemoteIpPrefix()) { + flowId = flowId + portSecurityRule.getSecurityRuleRemoteIpPrefix(); + matchBuilder = MatchUtils.addRemoteIpv6Prefix(matchBuilder, + new Ipv6Prefix(portSecurityRule + .getSecurityRuleRemoteIpPrefix()),null); + } + NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong); + flowId = flowId + "_Permit"; + syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false); + } + public void ingressACLTcpSyn(Long dpidLong, String segmentationId, String attachedMac, boolean write, Integer securityRulePortMin, Integer protoPortMatchPriority) { @@ -854,6 +926,25 @@ public class IngressAclService extends AbstractServiceInstance implements Ingres syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false); } + /** + * Add rule to ensure only DHCPv6 server traffic from the specified mac is allowed. + * + * @param dpidLong the dpid + * @param segmentationId the segmentation id + * @param dhcpMacAddress the DHCP server mac address + * @param write is write or delete + * @param protoPortMatchPriority the priority + */ + private void ingressAclDhcpv6AllowServerTraffic(Long dpidLong, String segmentationId, String dhcpMacAddress, + boolean write, Integer protoPortMatchPriority) { + + NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(dpidLong); + MatchBuilder matchBuilder = new MatchBuilder(); + MatchUtils.createDhcpv6ServerMatch(matchBuilder, dhcpMacAddress, 547, 546).build(); + String flowId = "Ingress_DHCPv6_Server" + segmentationId + "_" + dhcpMacAddress + "_Permit_"; + syncFlow(flowId, nodeBuilder, matchBuilder, protoPortMatchPriority, write, false, false); + } + /** * Add or remove flow to the node. * 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 7078486a92..cbb73c0d20 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 @@ -15,6 +15,7 @@ import java.util.List; import java.util.Map; 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.Ipv6Prefix; 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.types.rev131026.flow.MatchBuilder; @@ -27,6 +28,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4MatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv6MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.MetadataBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TcpFlagMatchBuilder; @@ -34,6 +36,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder; @@ -97,6 +100,7 @@ public class MatchUtils { public static final String UDP = "udp"; private static final int TCP_SYN = 0x0002; public static final String ICMP = "icmp"; + public static final String ICMPV6 = "icmpv6"; public static final short ALL_ICMP = -1; /** @@ -247,6 +251,32 @@ public class MatchUtils { return matchBuilder; } + /** + * Match ICMPv6 code and type + * + * @param matchBuilder MatchBuilder Object + * @param type short representing an ICMP type + * @param code short representing an ICMP code + * @return matchBuilder Map MatchBuilder Object with a match + */ + public static MatchBuilder createICMPv6Match(MatchBuilder matchBuilder, short type, short code) { + + // Build the IPv6 Match required per OVS Syntax + IpMatchBuilder ipmatch = new IpMatchBuilder(); + ipmatch.setIpProtocol((short) 58); + matchBuilder.setIpMatch(ipmatch.build()); + + // Build the ICMPv6 Match + Icmpv6MatchBuilder icmpv6match = new Icmpv6MatchBuilder(); + if (type != ALL_ICMP || code != ALL_ICMP) { + icmpv6match.setIcmpv6Type(type); + icmpv6match.setIcmpv6Code(code); + } + matchBuilder.setIcmpv6Match(icmpv6match.build()); + + return matchBuilder; + } + /** * @param matchBuilder MatchBuilder Object without a match yet * @param dstip String containing an IPv4 prefix @@ -442,6 +472,35 @@ public class MatchUtils { return matchBuilder; } + /** + * Create TCP Port Match + * + * @param matchBuilder MatchBuilder Object without a match yet + * @param ipProtocol Integer representing the IP protocol + * @return matchBuilder Map MatchBuilder Object with a match + */ + public static MatchBuilder createIpv6ProtocolMatch(MatchBuilder matchBuilder, short ipProtocol) { + + EthernetMatchBuilder ethType = new EthernetMatchBuilder(); + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x86DDL)); + 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. * @@ -922,7 +981,7 @@ public class MatchUtils { } /** - * Create a DHCP match with pot provided. + * Create a DHCP match with port provided. * * @param matchBuilder the match builder * @param srcPort the source port @@ -951,6 +1010,36 @@ public class MatchUtils { } + /** + * Create a DHCP match with port provided. + * + * @param matchBuilder the match builder + * @param srcPort the source port + * @param dstPort the destination port + * @return the DHCP match + */ + public static MatchBuilder createDhcpv6Match(MatchBuilder matchBuilder, + int srcPort, int dstPort) { + + EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder(); + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x86DDL)); + ethernetMatch.setEthernetType(ethTypeBuilder.build()); + matchBuilder.setEthernetMatch(ethernetMatch.build()); + + IpMatchBuilder ipmatch = new IpMatchBuilder(); + ipmatch.setIpProtocol(UDP_SHORT); + matchBuilder.setIpMatch(ipmatch.build()); + + UdpMatchBuilder udpmatch = new UdpMatchBuilder(); + udpmatch.setUdpSourcePort(new PortNumber(srcPort)); + udpmatch.setUdpDestinationPort(new PortNumber(dstPort)); + matchBuilder.setLayer4Match(udpmatch.build()); + + return matchBuilder; + + } + /** * Creates DHCP server packet match with DHCP mac address and port. * @@ -987,6 +1076,42 @@ public class MatchUtils { } + /** + * Creates DHCPv6 server packet match with DHCP mac address and port. + * + * @param matchBuilder the matchbuilder + * @param dhcpServerMac MAc address of the DHCP server of the subnet + * @param srcPort the source port + * @param dstPort the destination port + * @return the DHCP server match + */ + public static MatchBuilder createDhcpv6ServerMatch(MatchBuilder matchBuilder, String dhcpServerMac, int srcPort, + int dstPort) { + + EthernetMatchBuilder ethernetMatch = new EthernetMatchBuilder(); + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x86DDL)); + ethernetMatch.setEthernetType(ethTypeBuilder.build()); + matchBuilder.setEthernetMatch(ethernetMatch.build()); + + EthernetSourceBuilder ethSourceBuilder = new EthernetSourceBuilder(); + ethSourceBuilder.setAddress(new MacAddress(dhcpServerMac)); + ethernetMatch.setEthernetSource(ethSourceBuilder.build()); + matchBuilder.setEthernetMatch(ethernetMatch.build()); + + IpMatchBuilder ipmatch = new IpMatchBuilder(); + ipmatch.setIpProtocol(UDP_SHORT); + matchBuilder.setIpMatch(ipmatch.build()); + + UdpMatchBuilder udpmatch = new UdpMatchBuilder(); + udpmatch.setUdpSourcePort(new PortNumber(srcPort)); + udpmatch.setUdpDestinationPort(new PortNumber(dstPort)); + matchBuilder.setLayer4Match(udpmatch.build()); + + return matchBuilder; + + } + /** * Creates a Match with src ip address mac address set. * @param matchBuilder MatchBuilder Object @@ -1012,6 +1137,31 @@ public class MatchUtils { } + /** + * Creates a Match with src ip address mac address set. + * @param matchBuilder MatchBuilder Object + * @param srcip String containing an IPv6 prefix + * @param srcMac The source macAddress + * @return matchBuilder Map Object with a match + */ + public static MatchBuilder createSrcL3Ipv6MatchWithMac(MatchBuilder matchBuilder, Ipv6Prefix srcip, MacAddress srcMac) { + + Ipv6MatchBuilder ipv6MatchBuilder = new Ipv6MatchBuilder(); + ipv6MatchBuilder.setIpv6Source(new Ipv6Prefix(srcip)); + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x86DDL)); + EthernetMatchBuilder eth = new EthernetMatchBuilder(); + eth.setEthernetType(ethTypeBuilder.build()); + eth.setEthernetSource(new EthernetSourceBuilder() + .setAddress(srcMac) + .build()); + + matchBuilder.setLayer3Match(ipv6MatchBuilder.build()); + matchBuilder.setEthernetMatch(eth.build()); + return matchBuilder; + + } + /** * Creates a ether net match with ether type set to 0x0800L. * @param matchBuilder MatchBuilder Object @@ -1019,7 +1169,7 @@ public class MatchUtils { * @param dstMac The destination mac address * @return matchBuilder Map Object with a match */ - public static MatchBuilder createEtherMatchWithType(MatchBuilder matchBuilder,String srcMac, String dstMac) + public static MatchBuilder createV4EtherMatchWithType(MatchBuilder matchBuilder,String srcMac, String dstMac) { EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); ethTypeBuilder.setType(new EtherType(0x0800L)); @@ -1036,6 +1186,32 @@ public class MatchUtils { matchBuilder.setEthernetMatch(eth.build()); return matchBuilder; } + + /** + * Creates a ether net match with ether type set to 0x86DDL. + * @param matchBuilder MatchBuilder Object + * @param srcMac The source macAddress + * @param dstMac The destination mac address + * @return matchBuilder Map Object with a match + */ + public static MatchBuilder createV6EtherMatchWithType(MatchBuilder matchBuilder,String srcMac, String dstMac) + { + EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder(); + ethTypeBuilder.setType(new EtherType(0x86DDL)); + EthernetMatchBuilder eth = new EthernetMatchBuilder(); + eth.setEthernetType(ethTypeBuilder.build()); + if (null != srcMac) { + eth.setEthernetSource(new EthernetSourceBuilder() + .setAddress(new MacAddress(srcMac)).build()); + } + if (null != dstMac) { + eth.setEthernetDestination(new EthernetDestinationBuilder() + .setAddress(new MacAddress(dstMac)).build()); + } + matchBuilder.setEthernetMatch(eth.build()); + return matchBuilder; + } + /** * Adds remote Ip prefix to existing match. * @param matchBuilder The match builder @@ -1056,6 +1232,28 @@ public class MatchUtils { return matchBuilder; } + + /** + * Adds remote Ipv6 prefix to existing match. + * @param matchBuilder The match builder + * @param sourceIpPrefix The source IP prefix + * @param destIpPrefix The destination IP prefix + * @return matchBuilder Map Object with a match + */ + public static MatchBuilder addRemoteIpv6Prefix(MatchBuilder matchBuilder, + Ipv6Prefix sourceIpPrefix,Ipv6Prefix destIpPrefix) { + Ipv6MatchBuilder ipv6match = new Ipv6MatchBuilder(); + if (null != sourceIpPrefix) { + ipv6match.setIpv6Source(sourceIpPrefix); + } + if (null != destIpPrefix) { + ipv6match.setIpv6Destination(destIpPrefix); + } + matchBuilder.setLayer3Match(ipv6match.build()); + + return matchBuilder; + } + /** * Add a layer4 match to an existing match * @@ -1351,6 +1549,16 @@ public class MatchUtils { return new Ipv4Prefix(ipv4AddressString + "/32"); } + /** + * Create ipv6 prefix from ipv6 address, by appending /128 mask + * + * @param ipv6AddressString the ip address, in string format + * @return Ipv6Prefix with ipv6Address and /128 mask + */ + public static Ipv6Prefix iPv6PrefixFromIPv6Address(String ipv6AddressString) { + return new Ipv6Prefix(ipv6AddressString + "/128"); + } + /** * Converts port range into a set of masked port ranges. *