From f9a68e7f157541b9cc3e8944820ab218c4cdbb4b Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Tue, 29 Jan 2013 21:43:58 -0800 Subject: [PATCH] IPv6: Add vlan overlap checking --- .../configuration/ConfigurationManager.java | 2 +- .../ConfigurationManagerImpl.java | 45 +++++++++++++------ utils/src/com/cloud/utils/net/NetUtils.java | 23 ++++++++++ .../com/cloud/utils/net/NetUtilsTest.java | 5 +++ 4 files changed, 60 insertions(+), 15 deletions(-) diff --git a/server/src/com/cloud/configuration/ConfigurationManager.java b/server/src/com/cloud/configuration/ConfigurationManager.java index 58fdeeda2e2..09e8ac902b9 100644 --- a/server/src/com/cloud/configuration/ConfigurationManager.java +++ b/server/src/com/cloud/configuration/ConfigurationManager.java @@ -198,7 +198,7 @@ public interface ConfigurationManager extends ConfigurationService, Manager { boolean isDefault, Network.GuestType type, boolean systemOnly, Long serviceOfferingId, boolean conserveMode, Map> serviceCapabilityMap, boolean specifyIpRanges); - Vlan createVlanAndPublicIpRange(long zoneId, long networkId, long physicalNetworkId, boolean forVirtualNetwork, Long podId, String startIP, String endIP, String vlanGateway, String vlanNetmask, String vlanId, Account vlanOwner, String startIPv6, String endIPv6, String vlanGatewayv6, String vlanCidrv6) throws InsufficientCapacityException, ConcurrentOperationException, InvalidParameterValueException; + Vlan createVlanAndPublicIpRange(long zoneId, long networkId, long physicalNetworkId, boolean forVirtualNetwork, Long podId, String startIP, String endIP, String vlanGateway, String vlanNetmask, String vlanId, Account vlanOwner, String startIPv6, String endIPv6, String vlanIp6Gateway, String vlanIp6Cidr) throws InsufficientCapacityException, ConcurrentOperationException, InvalidParameterValueException; void createDefaultSystemNetworks(long zoneId) throws ConcurrentOperationException; diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index aee32340af4..c8acf3b1caa 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -2278,7 +2278,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura @DB public Vlan createVlanAndPublicIpRange(long zoneId, long networkId, long physicalNetworkId, boolean forVirtualNetwork, Long podId, String startIP, String endIP, String vlanGateway, String vlanNetmask, - String vlanId, Account vlanOwner, String startIPv6, String endIPv6, String vlanGatewayv6, String vlanCidrv6) { + String vlanId, Account vlanOwner, String startIPv6, String endIPv6, String vlanIp6Gateway, String vlanIp6Cidr) { Network network = _networkModel.getNetwork(networkId); boolean ipv4 = false, ipv6 = false; @@ -2372,15 +2372,14 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } if (ipv6) { - if (!NetUtils.isValidIpv6(vlanGatewayv6)) { + if (!NetUtils.isValidIpv6(vlanIp6Gateway)) { throw new InvalidParameterValueException("Please specify a valid IPv6 gateway"); } - if (!NetUtils.isValidIp6Cidr(vlanCidrv6)) { + if (!NetUtils.isValidIp6Cidr(vlanIp6Cidr)) { throw new InvalidParameterValueException("Please specify a valid IPv6 CIDR"); } } - // TODO skip all vlan check for ipv6 now if (ipv4) { String newVlanSubnet = NetUtils.getSubNet(vlanGateway, vlanNetmask); @@ -2426,7 +2425,7 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura List vlans = _vlanDao.listByZone(zone.getId()); for (VlanVO vlan : vlans) { String otherVlanGateway = vlan.getVlanGateway(); - // Continue if it's IPv6 + // Continue if it's not IPv4 if (otherVlanGateway == null) { continue; } @@ -2462,6 +2461,32 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } } } + + String ipv6Range = null; + if (ipv6) { + ipv6Range = startIPv6; + if (endIPv6 != null) { + ipv6Range += "-" + endIPv6; + } + + List vlans = _vlanDao.listByZone(zone.getId()); + for (VlanVO vlan : vlans) { + if (vlan.getIp6Gateway() == null) { + continue; + } + if (vlanId.equals(vlan.getVlanTag())) { + if (NetUtils.isIp6RangeOverlap(ipv6Range, vlan.getIp6Range())) { + throw new InvalidParameterValueException("The IPv6 range with tag: " + vlan.getVlanTag() + + " already has IPs that overlap with the new range. Please specify a different start IP/end IP."); + } + + if (!vlanIp6Gateway.equals(vlan.getIp6Gateway())) { + throw new InvalidParameterValueException("The IP range with tag: " + vlan.getVlanTag() + " has already been added with gateway " + vlan.getIp6Gateway() + + ". Please specify a different tag."); + } + } + } + } // Check if a guest VLAN is using the same tag if (_zoneDao.findVnet(zoneId, physicalNetworkId, vlanId).size() > 0) { @@ -2491,19 +2516,11 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura } } - String ipv6Range = null; - if (ipv6) { - ipv6Range = startIPv6; - if (endIPv6 != null) { - ipv6Range += "-" + endIPv6; - } - } - // Everything was fine, so persist the VLAN Transaction txn = Transaction.currentTxn(); txn.start(); - VlanVO vlan = new VlanVO(vlanType, vlanId, vlanGateway, vlanNetmask, zone.getId(), ipRange, networkId, physicalNetworkId, vlanGatewayv6, vlanCidrv6, ipv6Range); + VlanVO vlan = new VlanVO(vlanType, vlanId, vlanGateway, vlanNetmask, zone.getId(), ipRange, networkId, physicalNetworkId, vlanIp6Gateway, vlanIp6Cidr, ipv6Range); s_logger.debug("Saving vlan range " + vlan); vlan = _vlanDao.persist(vlan); diff --git a/utils/src/com/cloud/utils/net/NetUtils.java b/utils/src/com/cloud/utils/net/NetUtils.java index d121ff0a7c3..26026194ebb 100755 --- a/utils/src/com/cloud/utils/net/NetUtils.java +++ b/utils/src/com/cloud/utils/net/NetUtils.java @@ -42,6 +42,7 @@ import org.apache.log4j.Logger; import org.apache.log4j.xml.DOMConfigurator; import com.googlecode.ipv6.IPv6Address; +import com.googlecode.ipv6.IPv6AddressRange; import com.googlecode.ipv6.IPv6Network; import com.cloud.utils.IteratorUtil; @@ -1233,4 +1234,26 @@ public class NetUtils { } return false; } + + public static boolean isIp6RangeOverlap(String ipRange1, String ipRange2) { + String[] ips = ipRange1.split("-"); + String startIp1 = ips[0]; + String endIp1 = null; + if (ips.length > 1) { + endIp1 = ips[1]; + } + IPv6Address start1 = IPv6Address.fromString(startIp1); + IPv6Address end1 = IPv6Address.fromString(endIp1); + IPv6AddressRange range1 = IPv6AddressRange.fromFirstAndLast(start1, end1); + ips = ipRange2.split("-"); + String startIp2 = ips[0]; + String endIp2 = null; + if (ips.length > 1) { + endIp2 = ips[1]; + } + IPv6Address start2 = IPv6Address.fromString(startIp2); + IPv6Address end2 = IPv6Address.fromString(endIp2); + IPv6AddressRange range2 = IPv6AddressRange.fromFirstAndLast(start2, end2); + return range1.overlaps(range2); + } } diff --git a/utils/test/com/cloud/utils/net/NetUtilsTest.java b/utils/test/com/cloud/utils/net/NetUtilsTest.java index c256d6dbfc3..5336d93127a 100644 --- a/utils/test/com/cloud/utils/net/NetUtilsTest.java +++ b/utils/test/com/cloud/utils/net/NetUtilsTest.java @@ -96,5 +96,10 @@ public class NetUtilsTest extends TestCase { assertTrue(ip.compareTo(ipStart) >= 0); assertTrue(ip.compareTo(ipEnd) <= 0); } + assertFalse(NetUtils.isIp6RangeOverlap("1234:5678::1-1234:5678::ffff", "1234:5678:1::1-1234:5678:1::ffff")); + assertTrue(NetUtils.isIp6RangeOverlap("1234:5678::1-1234:5678::ffff", "1234:5678::2-1234:5678::f")); + assertTrue(NetUtils.isIp6RangeOverlap("1234:5678::f-1234:5678::ffff", "1234:5678::2-1234:5678::f")); + assertFalse(NetUtils.isIp6RangeOverlap("1234:5678::f-1234:5678::ffff", "1234:5678::2-1234:5678::e")); + assertFalse(NetUtils.isIp6RangeOverlap("1234:5678::f-1234:5678::f", "1234:5678::2-1234:5678::e")); } }