/* * Copyright 2014-present Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onosproject.net.host; import org.onlab.packet.IpAddress; import org.onlab.packet.IpPrefix; import java.util.Objects; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; /** * Represents a single IP address information on an interface. * * TODO: * - Add computation for the default broadcast address if it is not * specified * - Add explicit checks that each IP address or prefix belong to the * same IP version: IPv4/IPv6. * - Inside the copy constructor we should use copy constructors for each * field */ public class InterfaceIpAddress { private final IpAddress ipAddress; private final IpPrefix subnetAddress; private final IpAddress broadcastAddress; private final IpAddress peerAddress; /** * Copy constructor. * * @param other the object to copy from */ public InterfaceIpAddress(InterfaceIpAddress other) { // TODO: we should use copy constructors for each field this.ipAddress = other.ipAddress; this.subnetAddress = other.subnetAddress; this.broadcastAddress = other.broadcastAddress; this.peerAddress = other.peerAddress; } /** * Constructor for a given IP address and a subnet address. * * @param ipAddress the IP address * @param subnetAddress the IP subnet address */ public InterfaceIpAddress(IpAddress ipAddress, IpPrefix subnetAddress) { checkArgument(checkNotNull(ipAddress).version() == checkNotNull(subnetAddress).version(), "IP and subnet version mismatch"); this.ipAddress = ipAddress; this.subnetAddress = subnetAddress; this.broadcastAddress = computeBroadcastAddress(ipAddress, subnetAddress); this.peerAddress = null; } /** * Constructor for a given IP address and a subnet address. * * @param ipAddress the IP address * @param subnetAddress the IP subnet address * @param broadcastAddress the IP broadcast address. It can be used * to specify non-default broadcast address */ public InterfaceIpAddress(IpAddress ipAddress, IpPrefix subnetAddress, IpAddress broadcastAddress) { checkArgument(checkNotNull(ipAddress).version() == checkNotNull(subnetAddress).version(), "IP and subnet version mismatch"); this.ipAddress = ipAddress; this.subnetAddress = subnetAddress; this.broadcastAddress = broadcastAddress; this.peerAddress = null; } /** * Constructor for a given IP address and a subnet address. * * @param ipAddress the IP address * @param subnetAddress the IP subnet address * @param broadcastAddress the IP broadcast address. It can be used * to specify non-default broadcast address. It should be null for * point-to-point interfaces with a peer address * @param peerAddress the peer IP address for point-to-point interfaces */ public InterfaceIpAddress(IpAddress ipAddress, IpPrefix subnetAddress, IpAddress broadcastAddress, IpAddress peerAddress) { checkArgument(checkNotNull(ipAddress).version() == checkNotNull(subnetAddress).version(), "IP and subnet version mismatch"); this.ipAddress = ipAddress; this.subnetAddress = subnetAddress; this.broadcastAddress = broadcastAddress; this.peerAddress = peerAddress; } /** * Gets the IP address. * * @return the IP address */ public IpAddress ipAddress() { return ipAddress; } /** * Gets the IP subnet address. * * @return the IP subnet address */ public IpPrefix subnetAddress() { return subnetAddress; } /** * Gets the subnet IP broadcast address. * * @return the subnet IP broadcast address */ public IpAddress broadcastAddress() { return broadcastAddress; } /** * Gets the IP point-to-point interface peer address. * * @return the IP point-to-point interface peer address */ public IpAddress peerAddress() { return peerAddress; } /** * Converts a CIDR string literal to an interface IP address. * E.g. 10.0.0.1/24 * * @param value an IP address value in string form * @return an interface IP address * @throws IllegalArgumentException if the argument is invalid */ public static InterfaceIpAddress valueOf(String value) { String[] splits = value.split("/"); checkArgument(splits.length == 2, "Invalid IP address and prefix length format"); // NOTE: IpPrefix will mask-out the bits after the prefix length. IpPrefix subnet = IpPrefix.valueOf(value); IpAddress addr = IpAddress.valueOf(splits[0]); return new InterfaceIpAddress(addr, subnet); } /** * Compute the IP broadcast address. * * @param ipAddress base IP address * @param subnetAddress subnet specification * @return the IP broadcast address */ public static IpAddress computeBroadcastAddress(IpAddress ipAddress, IpPrefix subnetAddress) { if (ipAddress.isIp6()) { return null; } else { IpAddress maskedIP = IpAddress.makeMaskedAddress(ipAddress, subnetAddress.prefixLength()); int ipB = maskedIP.getIp4Address().toInt() | ((1 << (32 - subnetAddress.prefixLength())) - 1); return IpAddress.valueOf(ipB); } } @Override public boolean equals(Object other) { if (other == this) { return true; } if (!(other instanceof InterfaceIpAddress)) { return false; } InterfaceIpAddress otherAddr = (InterfaceIpAddress) other; return Objects.equals(this.ipAddress, otherAddr.ipAddress) && Objects.equals(this.subnetAddress, otherAddr.subnetAddress) && Objects.equals(this.broadcastAddress, otherAddr.broadcastAddress) && Objects.equals(this.peerAddress, otherAddr.peerAddress); } @Override public int hashCode() { return Objects.hash(ipAddress, subnetAddress, broadcastAddress, peerAddress); } @Override public String toString() { return ipAddress.toString() + "/" + subnetAddress.prefixLength(); } }