/** * Copyright 2011,2012, Big Switch Networks, Inc. * Originally created by David Erickson, Stanford University * * 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 net.floodlightcontroller.devicemanager.internal; import java.util.Date; import javax.annotation.Nonnull; import net.floodlightcontroller.core.web.serializers.IPv4Serializer; import net.floodlightcontroller.core.web.serializers.IPv6Serializer; import net.floodlightcontroller.core.web.serializers.DPIDSerializer; import net.floodlightcontroller.core.web.serializers.OFPortSerializer; import net.floodlightcontroller.core.web.serializers.VlanVidSerializer; import net.floodlightcontroller.core.web.serializers.MacSerializer; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import org.projectfloodlight.openflow.types.DatapathId; import org.projectfloodlight.openflow.types.IPv4Address; import org.projectfloodlight.openflow.types.IPv6Address; import org.projectfloodlight.openflow.types.MacAddress; import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.VlanVid; /** * An entity on the network is a visible trace of a device that corresponds * to a packet received from a particular interface on the edge of a network, * with a particular VLAN tag, and a particular MAC address, along with any * other packet characteristics we might want to consider as helpful for * disambiguating devices. * * Entities are the most basic element of devices; devices consist of one or * more entities. Entities are immutable once created, except for the last * seen timestamp. * * @author readams * */ public class Entity implements Comparable<Entity> { /** * Timeout for computing {@link Entity#activeSince}. * @see {@link Entity#activeSince} */ protected static int ACTIVITY_TIMEOUT = 30000; protected static final Date NO_DATE = new Date(0); /* Jan 1st 1970 00:00:00 */ /** * The MAC address associated with this entity */ protected MacAddress macAddress; /** * The IPv4 address associated with this entity, or null if no IP learned * from the network observation associated with this entity */ protected IPv4Address ipv4Address; /** * The IPv6 address associated with this entity, or null if no IP learned * from the network observation associated with this entity */ protected IPv6Address ipv6Address; /** * The VLAN tag on this entity, or null if untagged */ protected VlanVid vlan; /** * The DPID of the switch for the ingress point for this entity, * or null if not present */ protected DatapathId switchDPID; /** * The port number of the switch for the ingress point for this entity, * or null if not present */ protected OFPort switchPort; /** * The last time we observed this entity on the network */ protected Date lastSeenTimestamp; /** * The time between {@link Entity#activeSince} and * {@link Entity#lastSeenTimestamp} is a period of activity for this * entity where it was observed repeatedly. If, when the entity is * observed, the is longer ago than the activity timeout, * {@link Entity#lastSeenTimestamp} and {@link Entity#activeSince} will * be set to the current time. */ protected Date activeSince; // ************ // Constructors // ************ /** * Create a new entity * * @param macAddress * @param vlan * @param ipv4Address * @param ipv6Address * @param switchDPID * @param switchPort * @param lastSeenTimestamp */ public Entity(@Nonnull MacAddress macAddress, VlanVid vlan, @Nonnull IPv4Address ipv4Address, @Nonnull IPv6Address ipv6Address, @Nonnull DatapathId switchDPID, @Nonnull OFPort switchPort, @Nonnull Date lastSeenTimestamp) { if (macAddress == null) { throw new IllegalArgumentException("MAC address cannot be null. Try MacAddress.NONE if intention is 'no MAC'"); } if (ipv4Address == null) { throw new IllegalArgumentException("IPv4 address cannot be null. Try IPv4Address.NONE if intention is 'no IPv4'"); } if (ipv6Address == null) { throw new IllegalArgumentException("IPv6 address cannot be null. Try IPv6Address.NONE if intention is 'no IPv6'"); } /* VLAN can be null for 'don't care' in query searches */ if (switchDPID == null) { throw new IllegalArgumentException("Switch DPID cannot be null. Try DatapathId.NONE if intention is 'no DPID'"); } if (switchPort == null) { throw new IllegalArgumentException("Switch port cannot be null. Try OFPort.ZERO if intention is 'no port'"); } if (lastSeenTimestamp == null) { throw new IllegalArgumentException("Last seen time stamp cannot be null. Try Entity.NO_DATE if intention is 'no time'"); } this.macAddress = macAddress; this.ipv4Address = ipv4Address; this.ipv6Address = ipv6Address; this.vlan = vlan; this.switchDPID = switchDPID; this.switchPort = switchPort; this.lastSeenTimestamp = lastSeenTimestamp; this.activeSince = lastSeenTimestamp; } // *************** // Getters/Setters // *************** @JsonSerialize(using=MacSerializer.class) public MacAddress getMacAddress() { return macAddress; } @JsonSerialize(using=IPv4Serializer.class) public IPv4Address getIpv4Address() { return ipv4Address; } @JsonSerialize(using=IPv6Serializer.class) public IPv6Address getIpv6Address() { return ipv6Address; } @JsonSerialize(using=VlanVidSerializer.class) public VlanVid getVlan() { return vlan; } @JsonSerialize(using=DPIDSerializer.class) public DatapathId getSwitchDPID() { return switchDPID; } @JsonSerialize(using=OFPortSerializer.class) public OFPort getSwitchPort() { return switchPort; } @JsonIgnore public boolean hasSwitchPort() { return (switchDPID != null && !switchDPID.equals(DatapathId.NONE) && switchPort != null && !switchPort.equals(OFPort.ZERO)); } public Date getLastSeenTimestamp() { return lastSeenTimestamp; } /** * Set the last seen timestamp and also update {@link Entity#activeSince} * if appropriate * @param lastSeenTimestamp the new last seen timestamp * @see {@link Entity#activeSince} */ public void setLastSeenTimestamp(Date lastSeenTimestamp) { if (activeSince.equals(Entity.NO_DATE) || (activeSince.getTime() + ACTIVITY_TIMEOUT) < lastSeenTimestamp.getTime()) this.activeSince = lastSeenTimestamp; this.lastSeenTimestamp = lastSeenTimestamp; } public Date getActiveSince() { return activeSince; } public void setActiveSince(Date activeSince) { this.activeSince = activeSince; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((ipv4Address == null) ? 0 : ipv4Address.hashCode()); result = prime * result + ((ipv6Address == null) ? 0 : ipv6Address.hashCode()); result = prime * result + ((macAddress == null) ? 0 : macAddress.hashCode()); result = prime * result + ((switchDPID == null) ? 0 : switchDPID.hashCode()); result = prime * result + ((switchPort == null) ? 0 : switchPort.hashCode()); result = prime * result + ((vlan == null) ? 0 : vlan.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Entity other = (Entity) obj; if (hashCode() != obj.hashCode()) return false; if (ipv4Address == null) { if (other.ipv4Address != null) return false; } else if (!ipv4Address.equals(other.ipv4Address)) return false; if (ipv6Address == null) { if (other.ipv6Address != null) return false; } else if (!ipv6Address.equals(other.ipv6Address)) return false; if (macAddress == null) { if (other.macAddress != null) return false; } else if (!macAddress.equals(other.macAddress)) return false; if (switchDPID == null) { if (other.switchDPID != null) return false; } else if (!switchDPID.equals(other.switchDPID)) return false; if (switchPort == null) { if (other.switchPort != null) return false; } else if (!switchPort.equals(other.switchPort)) return false; if (vlan == null) { if (other.vlan != null) return false; } else if (!vlan.equals(other.vlan)) return false; return true; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("Entity [macAddress="); if (macAddress != null) { builder.append(macAddress.toString()); } else { builder.append("null"); } builder.append(", ipv4Address="); if (ipv4Address != null) { builder.append(ipv4Address.toString()); } else { builder.append("null"); } builder.append(", ipv6Address="); if (ipv4Address != null) { builder.append(ipv6Address.toString()); } else { builder.append("null"); } builder.append(", vlan="); if (vlan != null) { builder.append(vlan.getVlan()); } else { builder.append("null"); } builder.append(", switchDPID="); if (switchDPID != null) { builder.append(switchDPID.toString()); } else { builder.append("null"); } builder.append(", switchPort="); if (switchPort != null) { builder.append(switchPort.getPortNumber()); } else { builder.append("null"); } builder.append(", lastSeenTimestamp="); if (lastSeenTimestamp != null) { builder.append(lastSeenTimestamp == null? "null" : lastSeenTimestamp.toString()); } else { builder.append("null"); } builder.append(", activeSince="); if (activeSince != null) { builder.append(activeSince == null? "null" : activeSince.toString()); } else { builder.append("null"); } builder.append("]"); return builder.toString(); } @Override public int compareTo(Entity o) { if (macAddress.getLong() < o.macAddress.getLong()) return -1; if (macAddress.getLong() > o.macAddress.getLong()) return 1; int r; if (switchDPID == null) r = o.switchDPID == null ? 0 : -1; else if (o.switchDPID == null) r = 1; else r = switchDPID.compareTo(o.switchDPID); if (r != 0) return r; if (switchPort == null) r = o.switchPort == null ? 0 : -1; else if (o.switchPort == null) r = 1; else r = switchPort.compareTo(o.switchPort); if (r != 0) return r; if (ipv4Address == null) r = o.ipv4Address == null ? 0 : -1; else if (o.ipv4Address == null) r = 1; else r = ipv4Address.compareTo(o.ipv4Address); if (r != 0) return r; if (ipv6Address == null) r = o.ipv6Address == null ? 0 : -1; else if (o.ipv6Address == null) r = 1; else r = ipv6Address.compareTo(o.ipv6Address); if (r != 0) return r; if (vlan == null) r = o.vlan == null ? 0 : -1; else if (o.vlan == null) r = 1; else r = vlan.compareTo(o.vlan); if (r != 0) return r; return 0; } }