All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opendaylight.neutron.spi.NeutronSubnet Maven / Gradle / Ivy

There is a newer version: 0.16.4
Show newest version
/*
 * Copyright (c) 2013, 2015 IBM Corporation and others.  All rights reserved.
 *
 * 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.neutron.spi;

import com.google.common.net.InetAddresses;
import java.math.BigInteger;
import java.net.Inet6Address;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.apache.commons.net.util.SubnetUtils;
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public final class NeutronSubnet extends NeutronBaseAttributes {
    private static final Logger LOG = LoggerFactory.getLogger(NeutronSubnet.class);

    private static final long serialVersionUID = 1L;
    private static final int IPV4_VERSION = 4;
    private static final int IPV6_VERSION = 6;
    private static final int IPV6_LENGTH = 128;
    private static final int IPV6_LENGTH_BYTES = 8;
    private static final long IPV6_LSB_MASK = 0x000000FF;
    private static final int IPV6_BYTE_OFFSET = 7;

    // See OpenStack Network API v2.0 Reference for description of
    // annotated attributes

    @XmlElement(name = "network_id")
    String networkUUID;

    @XmlElement(defaultValue = "4", name = "ip_version")
    Integer ipVersion;

    @XmlElement(name = "cidr")
    String cidr;

    @XmlElement(name = "gateway_ip")
    String gatewayIp;

    @XmlElement(name = "dns_nameservers")
    List dnsNameservers;

    @XmlElement(name = "allocation_pools")
    List allocationPools;

    @XmlElement(name = "host_routes")
    List hostRoutes;

    @XmlElement(defaultValue = "true", name = "enable_dhcp")
    Boolean enableDHCP;

    @XmlElement(name = "ipv6_address_mode", nillable = true)
    String ipV6AddressMode;

    @XmlElement(name = "ipv6_ra_mode", nillable = true)
    String ipV6RaMode;

    public String getNetworkUUID() {
        return networkUUID;
    }

    public void setNetworkUUID(String networkUUID) {
        this.networkUUID = networkUUID;
    }

    public Integer getIpVersion() {
        return ipVersion;
    }

    public void setIpVersion(Integer ipVersion) {
        this.ipVersion = ipVersion;
    }

    public String getCidr() {
        return cidr;
    }

    public void setCidr(String cidr) {
        this.cidr = cidr;
    }

    public String getGatewayIp() {
        return gatewayIp;
    }

    public void setGatewayIp(String gatewayIp) {
        this.gatewayIp = gatewayIp;
    }

    public List getDnsNameservers() {
        return dnsNameservers;
    }

    public void setDnsNameservers(List dnsNameservers) {
        this.dnsNameservers = dnsNameservers;
    }

    public List getAllocationPools() {
        return allocationPools;
    }

    public void setAllocationPools(List allocationPools) {
        this.allocationPools = allocationPools;
    }

    public List getHostRoutes() {
        return hostRoutes;
    }

    public void setHostRoutes(List hostRoutes) {
        this.hostRoutes = hostRoutes;
    }

    public boolean isEnableDHCP() {
        if (enableDHCP == null) {
            return true;
        }
        return enableDHCP;
    }

    public Boolean getEnableDHCP() {
        return enableDHCP;
    }

    public void setEnableDHCP(Boolean newValue) {
        enableDHCP = newValue;
    }

    public String getIpV6AddressMode() {
        return ipV6AddressMode;
    }

    public void setIpV6AddressMode(String ipV6AddressMode) {
        this.ipV6AddressMode = ipV6AddressMode;
    }

    public String getIpV6RaMode() {
        return ipV6RaMode;
    }

    public void setIpV6RaMode(String ipV6RaMode) {
        this.ipV6RaMode = ipV6RaMode;
    }

    @Override
    protected boolean extractField(String field, NeutronSubnet ans) {
        switch (field) {
            case "network_id":
                ans.setNetworkUUID(this.getNetworkUUID());
                break;
            case "ip_version":
                ans.setIpVersion(this.getIpVersion());
                break;
            case "cidr":
                ans.setCidr(this.getCidr());
                break;
            case "gateway_ip":
                ans.setGatewayIp(this.getGatewayIp());
                break;
            case "dns_nameservers":
                List nsList = new ArrayList<>();
                nsList.addAll(this.getDnsNameservers());
                ans.setDnsNameservers(nsList);
                break;
            case "allocation_pools":
                List pools = new ArrayList<>();
                pools.addAll(this.getAllocationPools());
                ans.setAllocationPools(pools);
                break;
            case "host_routes":
                List routes = new ArrayList<>();
                routes.addAll(this.getHostRoutes());
                ans.setHostRoutes(routes);
                break;
            case "enable_dhcp":
                ans.setEnableDHCP(this.getEnableDHCP());
                break;
            case "ipv6_address_mode":
                ans.setIpV6AddressMode(this.getIpV6AddressMode());
                break;
            case "ipv6_ra_mode":
                ans.setIpV6RaMode(this.getIpV6RaMode());
                break;
            default:
                return super.extractField(field, ans);
        }
        return true;
    }

    /* test to see if the cidr address used to define this subnet
     * is a valid network address (an necessary condition when creating
     * a new subnet)
     */
    public boolean isValidCIDR() {
        // fix for Bug 2290 - need to wrap the existing test as
        // IPv4 because SubnetUtils doesn't support IPv6
        if (ipVersion == IPV4_VERSION) {
            try {
                SubnetUtils util = new SubnetUtils(cidr);
                SubnetInfo info = util.getInfo();
                if (!info.getNetworkAddress().equals(info.getAddress())) {
                    return false;
                }
            } catch (IllegalArgumentException e) {
                LOG.warn("Failure in isValidCIDR()", e);
                return false;
            }
            return true;
        }
        if (ipVersion == IPV6_VERSION) {
            // fix for Bug2290 - this is custom code because no classes
            // with ODL-friendly licenses have been found
            // extract address (in front of /) and length (after /)
            String[] parts = cidr.split("/");
            if (parts.length != 2) {
                return false;
            }
            int length = Integer.parseInt(parts[1]);
            //TODO?: limit check on length
            // convert to byte array
            byte[] addrBytes = ((Inet6Address) InetAddresses.forString(parts[0])).getAddress();
            for (int index = length; index < IPV6_LENGTH; index++) {
                if ((addrBytes[index / IPV6_LENGTH_BYTES] & IPV6_LSB_MASK
                        & 1 << IPV6_BYTE_OFFSET - index % IPV6_LENGTH_BYTES) != 0) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    /* test to see if the gateway IP specified overlaps with specified
     * allocation pools (an error condition when creating a new subnet
     * or assigning a gateway IP)
     */
    public boolean gatewayIp_Pool_overlap() {
        for (NeutronSubnetIpAllocationPool pool : allocationPools) {
            if (ipVersion == IPV4_VERSION && pool.contains(gatewayIp)) {
                return true;
            }
            if (ipVersion == IPV6_VERSION && pool.containsV6(gatewayIp)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void initDefaults() {
        if (enableDHCP == null) {
            enableDHCP = true;
        }
        if (ipVersion == null) {
            ipVersion = IPV4_VERSION;
        }
        if (dnsNameservers == null) {
            dnsNameservers = new ArrayList<>();
        }
        if (hostRoutes == null) {
            hostRoutes = new ArrayList<>();
        }
        if (allocationPools == null) {
            allocationPools = new ArrayList<>();
            if (ipVersion == IPV4_VERSION) {
                try {
                    SubnetUtils util = new SubnetUtils(cidr);
                    SubnetInfo info = util.getInfo();
                    if (gatewayIp == null || "".equals(gatewayIp)) {
                        gatewayIp = info.getLowAddress();
                    }
                    if (allocationPools.size() < 1) {
                        NeutronSubnetIpAllocationPool source = new NeutronSubnetIpAllocationPool(info.getLowAddress(),
                                info.getHighAddress());
                        allocationPools = source.splitPool(gatewayIp);
                    }
                } catch (IllegalArgumentException e) {
                    LOG.warn("Failure in initDefault()", e);
                    return;
                }
            }
            if (ipVersion == IPV6_VERSION) {
                String[] parts = cidr.split("/");
                if (parts.length != 2) {
                    return;
                }

                int length = Integer.parseInt(parts[1]);
                BigInteger lowAddressBi = NeutronSubnetIpAllocationPool.convertV6(parts[0]);
                String lowAddress = NeutronSubnetIpAllocationPool.bigIntegerToIp(lowAddressBi.add(BigInteger.ONE));
                BigInteger mask = BigInteger.ONE.shiftLeft(length).subtract(BigInteger.ONE);
                String highAddress = NeutronSubnetIpAllocationPool
                        .bigIntegerToIp(lowAddressBi.add(mask).subtract(BigInteger.ONE));
                if (gatewayIp == null || "".equals(gatewayIp)) {
                    gatewayIp = lowAddress;
                }
                if (allocationPools.size() < 1) {
                    NeutronSubnetIpAllocationPool source = new NeutronSubnetIpAllocationPool(lowAddress,
                            highAddress);
                    allocationPools = source.splitPoolV6(gatewayIp);
                }
            }
        }
    }

    /* this method tests to see if the supplied IPv4 address
     * is valid for this subnet or not
     */
    public boolean isValidIp(String ipAddress) {
        if (ipVersion == IPV4_VERSION) {
            try {
                SubnetUtils util = new SubnetUtils(cidr);
                SubnetInfo info = util.getInfo();
                return info.isInRange(ipAddress);
            } catch (IllegalArgumentException e) {
                LOG.warn("Failure in isValidIp()", e);
                return false;
            }
        }

        if (ipVersion == IPV6_VERSION) {
            String[] parts = cidr.split("/");
            int length = Integer.parseInt(parts[1]);
            byte[] cidrBytes = ((Inet6Address) InetAddresses.forString(parts[0])).getAddress();
            byte[] ipBytes = ((Inet6Address) InetAddresses.forString(ipAddress)).getAddress();
            for (int index = 0; index < length; index++) {
                if ((cidrBytes[index / IPV6_LENGTH_BYTES] & IPV6_LSB_MASK & 1 << IPV6_BYTE_OFFSET
                        - index % IPV6_LENGTH_BYTES) != (
                            ipBytes[index / IPV6_LENGTH_BYTES] & IPV6_LSB_MASK
                            & 1 << IPV6_BYTE_OFFSET - index % IPV6_LENGTH_BYTES)) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    /* method to get the lowest available address of the subnet.
     * go through all the allocation pools and keep the lowest of their
     * low addresses.
     */
    public String getLowAddr() {
        String ans = null;
        for (NeutronSubnetIpAllocationPool pool : allocationPools) {
            if (ans == null) {
                ans = pool.getPoolStart();
            } else {
                if (ipVersion == IPV4_VERSION && NeutronSubnetIpAllocationPool
                        .convert(pool.getPoolStart()) < NeutronSubnetIpAllocationPool.convert(ans)) {
                    ans = pool.getPoolStart();
                }
                if (ipVersion == IPV6_VERSION && NeutronSubnetIpAllocationPool.convertV6(pool.getPoolStart())
                        .compareTo(NeutronSubnetIpAllocationPool.convertV6(ans)) < 0) {
                    ans = pool.getPoolStart();
                }
            }
        }
        return ans;
    }

    @Override
    public String toString() {
        return "NeutronSubnet [subnetUUID=" + uuid + ", networkUUID=" + networkUUID + ", name=" + name + ", ipVersion="
                + ipVersion + ", cidr=" + cidr + ", gatewayIp=" + gatewayIp + ", dnsNameservers=" + dnsNameservers
                + ", allocationPools=" + allocationPools + ", hostRoutes=" + hostRoutes + ", enableDHCP=" + enableDHCP
                + ", tenantID=" + getTenantID() + ", ipv6AddressMode=" + ipV6AddressMode + ", ipv6RaMode=" + ipV6RaMode
                + "]";
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy