pankaj

Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next

Showing 120 changed files with 2101 additions and 1071 deletions
......@@ -18,18 +18,20 @@
<dependencies>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.4.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onlab-misc</artifactId>
</dependency>
</dependencies>
......
......@@ -41,5 +41,17 @@
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
</dependency>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onlab-misc</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
</dependencies>
</project>
......
......@@ -170,10 +170,6 @@ public class ReactiveForwarding {
// We don't yet support bufferids in the flowservice so packet out first.
packetOut(context, portNumber);
if (true) {
return;
}
// Install the flow rule to handle this type of message from now on.
Ethernet inPkt = context.inPacket().parsed();
TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
......
......@@ -16,4 +16,14 @@
<description>ONOS simple Mobility app</description>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onlab-misc</artifactId>
</dependency>
</dependencies>
</project>
......
......@@ -23,7 +23,8 @@
<module>foo</module>
<module>mobility</module>
<module>proxyarp</module>
<module>config</module>
<module>config</module>
<module>sdnip</module>
</modules>
<properties>
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-apps</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-sdnip</artifactId>
<packaging>bundle</packaging>
<description>SDN-IP peering application</description>
<dependencies>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.4.2</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
package org.onlab.onos.sdnip;
import static org.slf4j.LoggerFactory.getLogger;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.slf4j.Logger;
/**
* Placeholder SDN-IP component.
*/
@Component(immediate = true)
public class SdnIp {
private final Logger log = getLogger(getClass());
@Activate
protected void activate() {
log.debug("SDN-IP started");
}
@Deactivate
protected void deactivate() {
log.info("Stopped");
}
}
/**
* SDN-IP peering application.
*/
package org.onlab.onos.sdnip;
\ No newline at end of file
......@@ -141,7 +141,7 @@ public class TopologyResource extends BaseResource {
private ObjectNode json(ObjectMapper mapper, ElementId id, int group,
String label, boolean isOnline) {
return mapper.createObjectNode()
.put("name", id.uri().toString())
.put("name", id.toString())
.put("label", label)
.put("group", group)
.put("online", isOnline);
......@@ -202,7 +202,7 @@ public class TopologyResource extends BaseResource {
// Returns a formatted string for the element associated with the given
// connection point.
private static String id(ConnectPoint cp) {
return cp.elementId().uri().toString();
return cp.elementId().toString();
}
}
......
/**
* REST resources for the sample topology viewer application.
* Sample topology viewer application.
*/
package org.onlab.onos.tvue;
......
......@@ -21,14 +21,14 @@ public final class Comparators {
public static final Comparator<ElementId> ELEMENT_ID_COMPARATOR = new Comparator<ElementId>() {
@Override
public int compare(ElementId id1, ElementId id2) {
return id1.uri().toString().compareTo(id2.uri().toString());
return id1.toString().compareTo(id2.toString());
}
};
public static final Comparator<Element> ELEMENT_COMPARATOR = new Comparator<Element>() {
@Override
public int compare(Element e1, Element e2) {
return e1.id().uri().toString().compareTo(e2.id().uri().toString());
return e1.id().toString().compareTo(e2.id().toString());
}
};
......
package org.onlab.onos.cli;
import com.google.common.collect.Lists;
import org.apache.karaf.shell.commands.Command;
import org.onlab.onos.cluster.ClusterService;
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.MastershipService;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.DeviceMastershipService;
import java.util.Collections;
import java.util.List;
......@@ -23,7 +22,7 @@ public class MastersListCommand extends AbstractShellCommand {
@Override
protected void execute() {
ClusterService service = get(ClusterService.class);
DeviceMastershipService mastershipService = get(DeviceMastershipService.class);
MastershipService mastershipService = get(MastershipService.class);
List<ControllerNode> nodes = newArrayList(service.getNodes());
Collections.sort(nodes, Comparators.NODE_COMPARATOR);
ControllerNode self = service.getLocalNode();
......
......@@ -22,8 +22,10 @@ public class SummaryCommand extends AbstractShellCommand {
protected void execute() {
TopologyService topologyService = get(TopologyService.class);
Topology topology = topologyService.currentTopology();
print("version=%s, nodes=%d, devices=%d, links=%d, hosts=%d, clusters=%s, paths=%d, flows=%d, intents=%d",
get(CoreService.class).version().toString(),
print("node=%s, version=%s",
get(ClusterService.class).getLocalNode().ip(),
get(CoreService.class).version().toString());
print("nodes=%d, devices=%d, links=%d, hosts=%d, clusters=%s, paths=%d, flows=%d, intents=%d",
get(ClusterService.class).getNodes().size(),
get(DeviceService.class).getDeviceCount(),
get(LinkService.class).getLinkCount(),
......
......@@ -3,9 +3,9 @@ package org.onlab.onos.cli.net;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onlab.onos.cli.AbstractShellCommand;
import org.onlab.onos.cluster.MastershipAdminService;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.MastershipRole;
import org.onlab.onos.net.device.DeviceMastershipAdminService;
import static org.onlab.onos.net.DeviceId.deviceId;
......@@ -30,7 +30,7 @@ public class DeviceRoleCommand extends AbstractShellCommand {
@Override
protected void execute() {
DeviceMastershipAdminService service = get(DeviceMastershipAdminService.class);
MastershipAdminService service = get(MastershipAdminService.class);
MastershipRole mastershipRole = MastershipRole.valueOf(role.toUpperCase());
service.setRole(new NodeId(node), deviceId(uri), mastershipRole);
}
......
package org.onlab.onos.net.device;
package org.onlab.onos.cluster;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
/**
* Service for administering the inventory of device masterships.
*/
public interface DeviceMastershipAdminService {
public interface MastershipAdminService {
/**
* Applies the current mastership role for the specified device.
......
package org.onlab.onos.net.device;
package org.onlab.onos.cluster;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.event.AbstractEvent;
import org.onlab.onos.net.DeviceId;
/**
* Describes a device mastership event.
*/
public class DeviceMastershipEvent extends AbstractEvent<DeviceMastershipEvent.Type, DeviceId> {
public class MastershipEvent extends AbstractEvent<MastershipEvent.Type, DeviceId> {
//do we worry about explicitly setting slaves/equals? probably not,
//to keep it simple
......@@ -31,7 +30,7 @@ public class DeviceMastershipEvent extends AbstractEvent<DeviceMastershipEvent.T
* @param device event device subject
* @param master master ID subject
*/
public DeviceMastershipEvent(Type type, DeviceId device, NodeId master) {
public MastershipEvent(Type type, DeviceId device, NodeId master) {
super(type, device);
this.master = master;
}
......@@ -45,7 +44,7 @@ public class DeviceMastershipEvent extends AbstractEvent<DeviceMastershipEvent.T
* @param master master ID subject
* @param time occurrence time
*/
public DeviceMastershipEvent(Type type, DeviceId device, NodeId master, long time) {
public MastershipEvent(Type type, DeviceId device, NodeId master, long time) {
super(type, device, time);
this.master = master;
}
......
package org.onlab.onos.net.device;
package org.onlab.onos.cluster;
import org.onlab.onos.event.EventListener;
/**
* Entity capable of receiving device mastership-related events.
*/
public interface DeviceMastershipListener extends EventListener<DeviceMastershipEvent> {
public interface MastershipListener extends EventListener<MastershipEvent> {
}
......
package org.onlab.onos.net.device;
package org.onlab.onos.cluster;
import java.util.Set;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
......@@ -12,7 +11,7 @@ import org.onlab.onos.net.MastershipRole;
* determining mastership, but is not responsible for actually applying it
* to the devices; this falls on the device service.
*/
public interface DeviceMastershipService {
public interface MastershipService {
/**
* Returns the role of the local node for the specified device, without
......@@ -63,20 +62,20 @@ public interface DeviceMastershipService {
*
* @return the MastershipTermService for this mastership manager
*/
DeviceMastershipTermService requestTermService();
MastershipTermService requestTermService();
/**
* Adds the specified mastership change listener.
*
* @param listener the mastership listener
*/
void addListener(DeviceMastershipListener listener);
void addListener(MastershipListener listener);
/**
* Removes the specified mastership change listener.
*
* @param listener the mastership listener
*/
void removeListener(DeviceMastershipListener listener);
void removeListener(MastershipListener listener);
}
......
package org.onlab.onos.net.device;
package org.onlab.onos.cluster;
import java.util.Set;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
import org.onlab.onos.store.Store;
......@@ -11,7 +10,7 @@ import org.onlab.onos.store.Store;
* Manages inventory of mastership roles for devices, across controller
* instances; not intended for direct use.
*/
public interface DeviceMastershipStore extends Store<DeviceMastershipEvent, DeviceMastershipStoreDelegate> {
public interface MastershipStore extends Store<MastershipEvent, MastershipStoreDelegate> {
// three things to map: NodeId, DeviceId, MastershipRole
......@@ -55,7 +54,7 @@ public interface DeviceMastershipStore extends Store<DeviceMastershipEvent, Devi
* @param deviceId device identifier
* @return a mastership event
*/
DeviceMastershipEvent setMaster(NodeId nodeId, DeviceId deviceId);
MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId);
/**
* Returns the current master and number of past mastership hand-offs
......@@ -64,7 +63,7 @@ public interface DeviceMastershipStore extends Store<DeviceMastershipEvent, Devi
* @param deviceId the device identifier
* @return the current master's ID and the term value for device, or null
*/
DeviceMastershipTerm getTermFor(DeviceId deviceId);
MastershipTerm getTermFor(DeviceId deviceId);
/**
* Sets a controller instance's mastership role to STANDBY for a device.
......@@ -75,7 +74,7 @@ public interface DeviceMastershipStore extends Store<DeviceMastershipEvent, Devi
* @param deviceId device to revoke mastership role for
* @return a mastership event
*/
DeviceMastershipEvent setStandby(NodeId nodeId, DeviceId deviceId);
MastershipEvent setStandby(NodeId nodeId, DeviceId deviceId);
/**
* Allows a controller instance to give up its current role for a device.
......@@ -86,6 +85,6 @@ public interface DeviceMastershipStore extends Store<DeviceMastershipEvent, Devi
* @param deviceId device to revoke mastership role for
* @return a mastership event
*/
DeviceMastershipEvent relinquishRole(NodeId nodeId, DeviceId deviceId);
MastershipEvent relinquishRole(NodeId nodeId, DeviceId deviceId);
}
......
package org.onlab.onos.net.device;
package org.onlab.onos.cluster;
import org.onlab.onos.store.StoreDelegate;
/**
* DeviceMastership store delegate abstraction.
* Mastership store delegate abstraction.
*/
public interface DeviceMastershipStoreDelegate extends StoreDelegate<DeviceMastershipEvent> {
public interface MastershipStoreDelegate extends StoreDelegate<MastershipEvent> {
}
......
package org.onlab.onos.net.device;
package org.onlab.onos.cluster;
import java.util.Objects;
import org.onlab.onos.cluster.NodeId;
public final class DeviceMastershipTerm {
public final class MastershipTerm {
private final NodeId master;
private final int termNumber;
private DeviceMastershipTerm(NodeId master, int term) {
private MastershipTerm(NodeId master, int term) {
this.master = master;
this.termNumber = term;
}
public static DeviceMastershipTerm of(NodeId master, int term) {
return new DeviceMastershipTerm(master, term);
public static MastershipTerm of(NodeId master, int term) {
return new MastershipTerm(master, term);
}
public NodeId master() {
......@@ -36,8 +34,8 @@ public final class DeviceMastershipTerm {
if (this == other) {
return true;
}
if (other instanceof DeviceMastershipTerm) {
DeviceMastershipTerm that = (DeviceMastershipTerm) other;
if (other instanceof MastershipTerm) {
MastershipTerm that = (MastershipTerm) other;
if (!this.master.equals(that.master)) {
return false;
}
......
package org.onlab.onos.net.device;
package org.onlab.onos.cluster;
import org.onlab.onos.net.DeviceId;
......@@ -6,7 +6,7 @@ import org.onlab.onos.net.DeviceId;
/**
* Service to obtain mastership term information.
*/
public interface DeviceMastershipTermService {
public interface MastershipTermService {
// TBD: manage/increment per device mastership change
// or increment on any change
......@@ -16,5 +16,5 @@ public interface DeviceMastershipTermService {
* @param deviceId the identifier of the device
* @return current master's term.
*/
DeviceMastershipTerm getMastershipTerm(DeviceId deviceId);
MastershipTerm getMastershipTerm(DeviceId deviceId);
}
......
package org.onlab.onos.net;
import java.net.URI;
import java.util.Objects;
/**
* Immutable representation of a device identity.
*/
public final class DeviceId extends ElementId {
/**
* Represents either no device, or an unspecified device.
*/
public static final DeviceId NONE = deviceId("none:none");
private final URI uri;
private final String str;
// Public construction is prohibited
private DeviceId(URI uri) {
super(uri);
this.uri = uri;
this.str = uri.toString();
}
// Default constructor for serialization
protected DeviceId() {
this.uri = null;
this.str = null;
}
/**
......@@ -30,4 +47,36 @@ public final class DeviceId extends ElementId {
return deviceId(URI.create(string));
}
/**
* Returns the backing URI.
*
* @return backing URI
*/
public URI uri() {
return uri;
}
@Override
public int hashCode() {
return Objects.hash(str);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DeviceId) {
final DeviceId that = (DeviceId) obj;
return this.getClass() == that.getClass() &&
Objects.equals(this.str, that.str);
}
return false;
}
@Override
public String toString() {
return str;
}
}
......
package org.onlab.onos.net;
import java.net.URI;
import java.util.Objects;
/**
* Immutable representation of a network element identity.
*/
public abstract class ElementId {
private final URI uri;
private final String str;
// Default constructor for serialization
protected ElementId() {
this.uri = null;
this.str = null;
}
/**
* Creates an element identifier using the supplied URI.
*
* @param uri backing URI
*/
protected ElementId(URI uri) {
this.uri = uri;
this.str = uri.toString();
}
/**
* Returns the backing URI.
*
* @return backing URI
*/
public URI uri() {
return uri;
}
@Override
public int hashCode() {
return Objects.hash(str);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof ElementId) {
final ElementId that = (ElementId) obj;
return this.getClass() == that.getClass() &&
Objects.equals(this.str, that.str);
}
return false;
}
@Override
public String toString() {
return str;
}
}
......
......@@ -3,44 +3,69 @@ package org.onlab.onos.net;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import java.net.URI;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkArgument;
/**
* Immutable representation of a host identity.
*/
public final class HostId extends ElementId {
private static final String NIC = "nic";
/**
* Represents either no host, or an unspecified host; used for creating
* open ingress/egress edge links.
*/
public static final HostId NONE = hostId(NIC + ":none-0");
public static final HostId NONE = new HostId(MacAddress.ZERO, VlanId.NONE);
private static final int MAC_LENGTH = 17;
private static final int MIN_ID_LENGTH = 19;
private final MacAddress mac;
private final VlanId vlanId;
// Public construction is prohibited
private HostId(URI uri) {
super(uri);
private HostId(MacAddress mac, VlanId vlanId) {
this.mac = mac;
this.vlanId = vlanId;
}
// Default constructor for serialization
private HostId() {
this.mac = null;
this.vlanId = null;
}
/**
* Creates a device id using the supplied URI.
* Returns the host MAC address.
*
* @param uri device URI
* @return host identifier
* @return MAC address
*/
public MacAddress mac() {
return mac;
}
/**
* Returns the host MAC address.
*
* @return MAC address
*/
public static HostId hostId(URI uri) {
return new HostId(uri);
public VlanId vlanId() {
return vlanId;
}
/**
* Creates a device id using the supplied URI string.
* Creates a device id using the supplied ID string.
*
* @param string device URI string
* @return host identifier
*/
public static HostId hostId(String string) {
return hostId(URI.create(string));
checkArgument(string.length() >= MIN_ID_LENGTH,
"Host ID must be at least %s characters", MIN_ID_LENGTH);
MacAddress mac = MacAddress.valueOf(string.substring(0, MAC_LENGTH));
VlanId vlanId = VlanId.vlanId(Short.parseShort(string.substring(MAC_LENGTH + 1)));
return new HostId(mac, vlanId);
}
/**
......@@ -51,7 +76,7 @@ public final class HostId extends ElementId {
* @return host identifier
*/
public static HostId hostId(MacAddress mac, VlanId vlanId) {
return hostId(NIC + ":" + mac + "-" + vlanId);
return new HostId(mac, vlanId);
}
/**
......@@ -64,4 +89,26 @@ public final class HostId extends ElementId {
return hostId(mac, VlanId.vlanId(VlanId.UNTAGGED));
}
public String toString() {
return mac + "/" + vlanId;
}
@Override
public int hashCode() {
return Objects.hash(mac, vlanId);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof HostId) {
final HostId other = (HostId) obj;
return Objects.equals(this.mac, other.mac) &&
Objects.equals(this.vlanId, other.vlanId);
}
return false;
}
}
......
package org.onlab.onos.net;
import static org.onlab.onos.net.PortNumber.P0;
/**
* Representation of a network edge location where an end-station host is
* connected.
*/
public class HostLocation extends ConnectPoint {
/**
* Represents a no location or an unknown location.
*/
public static final HostLocation NONE = new HostLocation(DeviceId.NONE, P0, 0L);
// Note that time is explicitly excluded from the notion of equality.
private final long time;
......
package org.onlab.onos.net;
/**
* Representation of a network resource.
*/
public interface NetworkResource {
}
......@@ -4,6 +4,8 @@ import org.onlab.onos.net.AbstractDescription;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.SparseAnnotations;
import com.google.common.base.MoreObjects;
/**
* Default implementation of immutable port description.
*/
......@@ -48,6 +50,15 @@ public class DefaultPortDescription extends AbstractDescription
return isEnabled;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("number", number)
.add("isEnabled", isEnabled)
.add("annotations", annotations())
.toString();
}
// default constructor for serialization
private DefaultPortDescription() {
this.number = null;
......
package org.onlab.onos.net.host;
import com.google.common.collect.ImmutableSet;
import org.onlab.onos.net.AbstractDescription;
import org.onlab.onos.net.HostLocation;
import org.onlab.onos.net.SparseAnnotations;
......@@ -8,9 +7,6 @@ import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import java.util.HashSet;
import java.util.Set;
import static com.google.common.base.MoreObjects.toStringHelper;
/**
......@@ -22,7 +18,7 @@ public class DefaultHostDescription extends AbstractDescription
private final MacAddress mac;
private final VlanId vlan;
private final HostLocation location;
private final Set<IpPrefix> ips;
private final IpPrefix ip;
/**
* Creates a host description using the supplied information.
......@@ -35,7 +31,7 @@ public class DefaultHostDescription extends AbstractDescription
public DefaultHostDescription(MacAddress mac, VlanId vlan,
HostLocation location,
SparseAnnotations... annotations) {
this(mac, vlan, location, new HashSet<IpPrefix>(), annotations);
this(mac, vlan, location, null, annotations);
}
/**
......@@ -44,17 +40,17 @@ public class DefaultHostDescription extends AbstractDescription
* @param mac host MAC address
* @param vlan host VLAN identifier
* @param location host location
* @param ips of host IP addresses
* @param ip host IP address
* @param annotations optional key/value annotations map
*/
public DefaultHostDescription(MacAddress mac, VlanId vlan,
HostLocation location, Set<IpPrefix> ips,
HostLocation location, IpPrefix ip,
SparseAnnotations... annotations) {
super(annotations);
this.mac = mac;
this.vlan = vlan;
this.location = location;
this.ips = new HashSet<>(ips);
this.ip = ip;
}
@Override
......@@ -73,8 +69,8 @@ public class DefaultHostDescription extends AbstractDescription
}
@Override
public Set<IpPrefix> ipAddresses() {
return ImmutableSet.copyOf(ips);
public IpPrefix ipAddress() {
return ip;
}
@Override
......@@ -83,7 +79,7 @@ public class DefaultHostDescription extends AbstractDescription
.add("mac", mac)
.add("vlan", vlan)
.add("location", location)
.add("ipAddresses", ips)
.add("ipAddress", ip)
.toString();
}
......
package org.onlab.onos.net.host;
import java.util.Set;
import org.onlab.onos.net.Description;
import org.onlab.onos.net.HostLocation;
import org.onlab.packet.IpPrefix;
......@@ -35,10 +33,10 @@ public interface HostDescription extends Description {
HostLocation location();
/**
* Returns zero or more IP address(es) associated with this host's MAC.
* Returns the IP address associated with this host's MAC.
*
* @return a set of IP addresses.
* @return host IP address
*/
Set<IpPrefix> ipAddresses();
IpPrefix ipAddress();
}
......
package org.onlab.onos.store;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.DeviceMastershipTerm;
//TODO: Consider renaming to DeviceClockProviderService?
/**
......@@ -16,5 +16,5 @@ public interface ClockProviderService {
* @param deviceId device identifier.
* @param term mastership term.
*/
public void setMastershipTerm(DeviceId deviceId, DeviceMastershipTerm term);
public void setMastershipTerm(DeviceId deviceId, MastershipTerm term);
}
......
package org.onlab.onos;
import java.util.Objects;
/**
* Test application ID.
*/
public class TestApplicationId implements ApplicationId {
private final String name;
private final short id;
public TestApplicationId(String name) {
this.name = name;
this.id = (short) Objects.hash(name);
}
public static ApplicationId create(String name) {
return new TestApplicationId(name);
}
@Override
public short id() {
return id;
}
@Override
public String name() {
return name;
}
}
......@@ -2,16 +2,13 @@ package org.onlab.onos.cluster;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
import org.onlab.onos.net.device.DeviceMastershipListener;
import org.onlab.onos.net.device.DeviceMastershipService;
import org.onlab.onos.net.device.DeviceMastershipTermService;
import java.util.Set;
/**
* Test adapter for mastership service.
*/
public class MastershipServiceAdapter implements DeviceMastershipService {
public class MastershipServiceAdapter implements MastershipService {
@Override
public MastershipRole getLocalRole(DeviceId deviceId) {
return null;
......@@ -37,15 +34,15 @@ public class MastershipServiceAdapter implements DeviceMastershipService {
}
@Override
public void addListener(DeviceMastershipListener listener) {
public void addListener(MastershipListener listener) {
}
@Override
public void removeListener(DeviceMastershipListener listener) {
public void removeListener(MastershipListener listener) {
}
@Override
public DeviceMastershipTermService requestTermService() {
public MastershipTermService requestTermService() {
return null;
}
}
......
......@@ -3,7 +3,6 @@ package org.onlab.onos.cluster;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.onlab.onos.net.device.DeviceMastershipTerm;
import com.google.common.testing.EqualsTester;
......@@ -12,10 +11,10 @@ public class MastershipTermTest {
private static final NodeId N1 = new NodeId("foo");
private static final NodeId N2 = new NodeId("bar");
private static final DeviceMastershipTerm TERM1 = DeviceMastershipTerm.of(N1, 0);
private static final DeviceMastershipTerm TERM2 = DeviceMastershipTerm.of(N2, 1);
private static final DeviceMastershipTerm TERM3 = DeviceMastershipTerm.of(N2, 1);
private static final DeviceMastershipTerm TERM4 = DeviceMastershipTerm.of(N1, 1);
private static final MastershipTerm TERM1 = MastershipTerm.of(N1, 0);
private static final MastershipTerm TERM2 = MastershipTerm.of(N2, 1);
private static final MastershipTerm TERM3 = MastershipTerm.of(N2, 1);
private static final MastershipTerm TERM4 = MastershipTerm.of(N1, 1);
@Test
public void basics() {
......@@ -25,7 +24,7 @@ public class MastershipTermTest {
@Test
public void testEquality() {
new EqualsTester().addEqualityGroup(DeviceMastershipTerm.of(N1, 0), TERM1)
new EqualsTester().addEqualityGroup(MastershipTerm.of(N1, 0), TERM1)
.addEqualityGroup(TERM2, TERM3)
.addEqualityGroup(TERM4);
}
......
......@@ -45,15 +45,18 @@ public class AbstractEventAccumulatorTest {
public void timeTrigger() {
TestAccumulator accumulator = new TestAccumulator();
accumulator.add(new TestEvent(FOO, "a"));
delay(40);
delay(30);
assertTrue("should not have fired yet", accumulator.batch.isEmpty());
accumulator.add(new TestEvent(FOO, "b"));
delay(40);
delay(30);
assertTrue("should not have fired yet", accumulator.batch.isEmpty());
accumulator.add(new TestEvent(FOO, "c"));
delay(40);
delay(30);
assertTrue("should not have fired yet", accumulator.batch.isEmpty());
accumulator.add(new TestEvent(FOO, "d"));
delay(30);
assertFalse("should have fired", accumulator.batch.isEmpty());
assertEquals("incorrect batch", "abc", accumulator.batch);
assertEquals("incorrect batch", "abcd", accumulator.batch);
}
@Test
......
......@@ -18,8 +18,8 @@ public class DefaultEdgeLinkTest {
private static final ProviderId PID = new ProviderId("of", "foo");
private static final DeviceId DID1 = deviceId("of:foo");
private static final HostId HID1 = hostId("nic:foobar");
private static final HostId HID2 = hostId("nic:barfoo");
private static final HostId HID1 = hostId("00:00:00:00:00:01/-1");
private static final HostId HID2 = hostId("00:00:00:00:00:01/-1");
private static final PortNumber P0 = portNumber(0);
private static final PortNumber P1 = portNumber(1);
......@@ -35,12 +35,8 @@ public class DefaultEdgeLinkTest {
EdgeLink l4 = new DefaultEdgeLink(PID, cp(HID2, P0),
new HostLocation(DID1, P1, 123L), false);
EdgeLink l5 = new DefaultEdgeLink(PID, cp(HID1, P0),
new HostLocation(DID1, P1, 123L), false);
new EqualsTester().addEqualityGroup(l1, l2)
.addEqualityGroup(l3, l4)
.addEqualityGroup(l5)
.testEquals();
}
......
......@@ -8,7 +8,7 @@ import static org.onlab.onos.net.DeviceId.deviceId;
/**
* Test of the device identifier.
*/
public class DeviceIdTest extends ElementIdTest {
public class DeviceIdTest {
@Test
public void basics() {
......
package org.onlab.onos.net;
import com.google.common.testing.EqualsTester;
import org.junit.Test;
import java.net.URI;
import static org.junit.Assert.assertEquals;
/**
* Test of the network element identifier.
*/
public class ElementIdTest {
private static class FooId extends ElementId {
public FooId(URI uri) {
super(uri);
}
}
public static URI uri(String str) {
return URI.create(str);
}
@Test
public void basics() {
new EqualsTester()
.addEqualityGroup(new FooId(uri("of:foo")),
new FooId(uri("of:foo")))
.addEqualityGroup(new FooId(uri("of:bar")))
.testEquals();
assertEquals("wrong uri", uri("ofcfg:foo"),
new FooId(uri("ofcfg:foo")).uri());
}
}
......@@ -11,20 +11,18 @@ import static org.onlab.onos.net.HostId.hostId;
/**
* Test for the host identifier.
*/
public class HostIdTest extends ElementIdTest {
public class HostIdTest {
private static final MacAddress MAC1 = MacAddress.valueOf("00:11:00:00:00:01");
private static final MacAddress MAC2 = MacAddress.valueOf("00:22:00:00:00:02");
private static final VlanId VLAN1 = VlanId.vlanId((short) 11);
private static final VlanId VLAN2 = VlanId.vlanId((short) 22);
@Override
@Test
public void basics() {
new EqualsTester()
.addEqualityGroup(hostId("nic:00:11:00:00:00:01-11"),
hostId(MAC1, VLAN1))
.addEqualityGroup(hostId(MAC2, VLAN2))
.addEqualityGroup(hostId(MAC1, VLAN1), hostId(MAC1, VLAN1))
.addEqualityGroup(hostId(MAC2, VLAN2), hostId(MAC2, VLAN2))
.testEquals();
}
......
......@@ -31,7 +31,7 @@ public final class NetTestTools {
// Short-hand for producing a host id from a string
public static HostId hid(String id) {
return hostId("nic:" + id);
return hostId(id);
}
// Crates a new device with the specified id
......
......@@ -10,9 +10,8 @@ import com.google.common.testing.EqualsTester;
/**
* Test of the port number.
*/
public class PortNumberTest extends ElementIdTest {
public class PortNumberTest {
@Override
@Test
public void basics() {
new EqualsTester()
......
package org.onlab.onos.net.host;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Set;
import org.junit.Test;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.HostLocation;
......@@ -13,7 +8,8 @@ import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import com.google.common.collect.Sets;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Test for the default host description.
......@@ -22,24 +18,22 @@ public class DefualtHostDecriptionTest {
private static final MacAddress MAC = MacAddress.valueOf("00:00:11:00:00:01");
private static final VlanId VLAN = VlanId.vlanId((short) 10);
private static final IpPrefix IP = IpPrefix.valueOf("10.0.0.1");
private static final HostLocation LOC = new HostLocation(
DeviceId.deviceId("of:foo"),
PortNumber.portNumber(100),
123L
);
private static final Set<IpPrefix> IPS = Sets.newHashSet(
IpPrefix.valueOf("10.0.0.1"),
IpPrefix.valueOf("10.0.0.2")
);
DeviceId.deviceId("of:foo"),
PortNumber.portNumber(100),
123L
);
@Test
public void basics() {
HostDescription host =
new DefaultHostDescription(MAC, VLAN, LOC, IPS);
new DefaultHostDescription(MAC, VLAN, LOC, IP);
assertEquals("incorrect mac", MAC, host.hwAddress());
assertEquals("incorrect vlan", VLAN, host.vlan());
assertEquals("incorrect location", LOC, host.location());
assertTrue("incorrect ip's", IPS.equals(host.ipAddresses()));
assertEquals("incorrect ip's", IP, host.ipAddress());
assertTrue("incorrect toString", host.toString().contains("vlan=10"));
}
......
......@@ -14,25 +14,25 @@ import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.cluster.ClusterEvent;
import org.onlab.onos.cluster.ClusterEventListener;
import org.onlab.onos.cluster.ClusterService;
import org.onlab.onos.cluster.MastershipAdminService;
import org.onlab.onos.cluster.MastershipEvent;
import org.onlab.onos.cluster.MastershipListener;
import org.onlab.onos.cluster.MastershipService;
import org.onlab.onos.cluster.MastershipStore;
import org.onlab.onos.cluster.MastershipStoreDelegate;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.MastershipTermService;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.event.AbstractListenerRegistry;
import org.onlab.onos.event.EventDeliveryService;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
import org.onlab.onos.net.device.DeviceMastershipAdminService;
import org.onlab.onos.net.device.DeviceMastershipEvent;
import org.onlab.onos.net.device.DeviceMastershipListener;
import org.onlab.onos.net.device.DeviceMastershipService;
import org.onlab.onos.net.device.DeviceMastershipStore;
import org.onlab.onos.net.device.DeviceMastershipStoreDelegate;
import org.onlab.onos.net.device.DeviceMastershipTerm;
import org.onlab.onos.net.device.DeviceMastershipTermService;
import org.slf4j.Logger;
@Component(immediate = true)
@Service
public class MastershipManager
implements DeviceMastershipService, DeviceMastershipAdminService {
implements MastershipService, MastershipAdminService {
private static final String NODE_ID_NULL = "Node ID cannot be null";
private static final String DEVICE_ID_NULL = "Device ID cannot be null";
......@@ -40,13 +40,13 @@ implements DeviceMastershipService, DeviceMastershipAdminService {
private final Logger log = getLogger(getClass());
protected final AbstractListenerRegistry<DeviceMastershipEvent, DeviceMastershipListener>
protected final AbstractListenerRegistry<MastershipEvent, MastershipListener>
listenerRegistry = new AbstractListenerRegistry<>();
private final DeviceMastershipStoreDelegate delegate = new InternalDelegate();
private final MastershipStoreDelegate delegate = new InternalDelegate();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceMastershipStore store;
protected MastershipStore store;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected EventDeliveryService eventDispatcher;
......@@ -58,7 +58,7 @@ implements DeviceMastershipService, DeviceMastershipAdminService {
@Activate
public void activate() {
eventDispatcher.addSink(DeviceMastershipEvent.class, listenerRegistry);
eventDispatcher.addSink(MastershipEvent.class, listenerRegistry);
clusterService.addListener(clusterListener);
store.setDelegate(delegate);
log.info("Started");
......@@ -66,7 +66,7 @@ implements DeviceMastershipService, DeviceMastershipAdminService {
@Deactivate
public void deactivate() {
eventDispatcher.removeSink(DeviceMastershipEvent.class);
eventDispatcher.removeSink(MastershipEvent.class);
clusterService.removeListener(clusterListener);
store.unsetDelegate(delegate);
log.info("Stopped");
......@@ -78,7 +78,7 @@ implements DeviceMastershipService, DeviceMastershipAdminService {
checkNotNull(deviceId, DEVICE_ID_NULL);
checkNotNull(role, ROLE_NULL);
DeviceMastershipEvent event = null;
MastershipEvent event = null;
if (role.equals(MastershipRole.MASTER)) {
event = store.setMaster(nodeId, deviceId);
} else {
......@@ -98,7 +98,7 @@ implements DeviceMastershipService, DeviceMastershipAdminService {
@Override
public void relinquishMastership(DeviceId deviceId) {
DeviceMastershipEvent event = null;
MastershipEvent event = null;
event = store.relinquishRole(
clusterService.getLocalNode().id(), deviceId);
......@@ -127,18 +127,18 @@ implements DeviceMastershipService, DeviceMastershipAdminService {
@Override
public DeviceMastershipTermService requestTermService() {
public MastershipTermService requestTermService() {
return new InternalMastershipTermService();
}
@Override
public void addListener(DeviceMastershipListener listener) {
public void addListener(MastershipListener listener) {
checkNotNull(listener);
listenerRegistry.addListener(listener);
}
@Override
public void removeListener(DeviceMastershipListener listener) {
public void removeListener(MastershipListener listener) {
checkNotNull(listener);
listenerRegistry.removeListener(listener);
}
......@@ -146,16 +146,16 @@ implements DeviceMastershipService, DeviceMastershipAdminService {
// FIXME: provide wiring to allow events to be triggered by changes within the store
// Posts the specified event to the local event dispatcher.
private void post(DeviceMastershipEvent event) {
private void post(MastershipEvent event) {
if (event != null && eventDispatcher != null) {
eventDispatcher.post(event);
}
}
private class InternalMastershipTermService implements DeviceMastershipTermService {
private class InternalMastershipTermService implements MastershipTermService {
@Override
public DeviceMastershipTerm getMastershipTerm(DeviceId deviceId) {
public MastershipTerm getMastershipTerm(DeviceId deviceId) {
return store.getTermFor(deviceId);
}
......@@ -181,10 +181,10 @@ implements DeviceMastershipService, DeviceMastershipAdminService {
}
public class InternalDelegate implements DeviceMastershipStoreDelegate {
public class InternalDelegate implements MastershipStoreDelegate {
@Override
public void notify(DeviceMastershipEvent event) {
public void notify(MastershipEvent event) {
log.info("dispatching mastership event {}", event);
eventDispatcher.post(event);
}
......
......@@ -13,6 +13,11 @@ import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.cluster.ClusterService;
import org.onlab.onos.cluster.MastershipEvent;
import org.onlab.onos.cluster.MastershipListener;
import org.onlab.onos.cluster.MastershipService;
import org.onlab.onos.cluster.MastershipTermService;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.event.AbstractListenerRegistry;
import org.onlab.onos.event.EventDeliveryService;
......@@ -31,11 +36,6 @@ import org.onlab.onos.net.device.DeviceProviderService;
import org.onlab.onos.net.device.DeviceService;
import org.onlab.onos.net.device.DeviceStore;
import org.onlab.onos.net.device.DeviceStoreDelegate;
import org.onlab.onos.net.device.DeviceMastershipEvent;
import org.onlab.onos.net.device.DeviceMastershipListener;
import org.onlab.onos.net.device.DeviceMastershipService;
import org.onlab.onos.net.device.DeviceMastershipTerm;
import org.onlab.onos.net.device.DeviceMastershipTermService;
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.AbstractProviderRegistry;
import org.onlab.onos.net.provider.AbstractProviderService;
......@@ -64,7 +64,7 @@ public class DeviceManager
private final DeviceStoreDelegate delegate = new InternalStoreDelegate();
private final DeviceMastershipListener mastershipListener = new InternalMastershipListener();
private final MastershipListener mastershipListener = new InternalMastershipListener();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceStore store;
......@@ -76,9 +76,9 @@ public class DeviceManager
protected ClusterService clusterService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceMastershipService mastershipService;
protected MastershipService mastershipService;
protected DeviceMastershipTermService termService;
protected MastershipTermService termService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClockProviderService clockProviderService;
......@@ -209,7 +209,7 @@ public class DeviceManager
return;
}
DeviceMastershipTerm term = mastershipService.requestTermService()
MastershipTerm term = mastershipService.requestTermService()
.getMastershipTerm(deviceId);
if (!term.master().equals(clusterService.getLocalNode().id())) {
// lost mastership after requestRole told this instance was MASTER.
......@@ -320,16 +320,16 @@ public class DeviceManager
}
// Intercepts mastership events
private class InternalMastershipListener implements DeviceMastershipListener {
private class InternalMastershipListener implements MastershipListener {
@Override
public void event(DeviceMastershipEvent event) {
public void event(MastershipEvent event) {
final DeviceId did = event.subject();
if (isAvailable(did)) {
final NodeId myNodeId = clusterService.getLocalNode().id();
if (myNodeId.equals(event.master())) {
DeviceMastershipTerm term = termService.getMastershipTerm(did);
MastershipTerm term = termService.getMastershipTerm(did);
if (term.master().equals(myNodeId)) {
// only set the new term if I am the master
......
......@@ -168,7 +168,6 @@ public class HostManager
checkNotNull(hostId, HOST_ID_NULL);
HostEvent event = store.removeHost(hostId);
if (event != null) {
log.info("Host {} administratively removed", hostId);
post(event);
}
}
......@@ -214,7 +213,6 @@ public class HostManager
HostEvent event = store.createOrUpdateHost(provider().id(), hostId,
hostDescription);
if (event != null) {
log.debug("Host {} detected", hostId);
post(event);
}
}
......@@ -225,7 +223,6 @@ public class HostManager
checkValidity();
HostEvent event = store.removeHost(hostId);
if (event != null) {
log.debug("Host {} vanished", hostId);
post(event);
}
}
......
......@@ -22,9 +22,9 @@ import org.onlab.onos.net.Link;
import org.onlab.onos.net.Path;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.topology.PathService;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.net.topology.LinkWeight;
import org.onlab.onos.net.topology.PathService;
import org.onlab.onos.net.topology.Topology;
import org.onlab.onos.net.topology.TopologyService;
import org.slf4j.Logger;
......@@ -33,7 +33,6 @@ import java.util.List;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.onos.net.DeviceId.deviceId;
import static org.slf4j.LoggerFactory.getLogger;
/**
......@@ -162,8 +161,8 @@ public class PathManager implements PathService {
// edge link since the src or dst are really an infrastructure device.
private static class NotHost extends DefaultEdgeLink implements EdgeLink {
NotHost() {
super(PID, new ConnectPoint(HostId.hostId("nic:none"), P0),
new HostLocation(deviceId("none:none"), P0, 0L), false);
super(PID, new ConnectPoint(HostId.NONE, P0),
new HostLocation(DeviceId.NONE, P0, 0L), false);
}
}
}
......
......@@ -10,11 +10,11 @@ import org.onlab.onos.cluster.ClusterService;
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.ControllerNode.State;
import org.onlab.onos.cluster.DefaultControllerNode;
import org.onlab.onos.cluster.MastershipService;
import org.onlab.onos.cluster.MastershipTermService;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.event.impl.TestEventDispatcher;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.DeviceMastershipService;
import org.onlab.onos.net.device.DeviceMastershipTermService;
import org.onlab.onos.store.trivial.impl.SimpleMastershipStore;
import org.onlab.packet.IpPrefix;
......@@ -34,7 +34,7 @@ public class MastershipManagerTest {
private static final DeviceId DEV_OTHER = DeviceId.deviceId("of:2");
private MastershipManager mgr;
protected DeviceMastershipService service;
protected MastershipService service;
@Before
public void setUp() {
......@@ -120,7 +120,7 @@ public class MastershipManagerTest {
@Test
public void termService() {
DeviceMastershipTermService ts = mgr.requestTermService();
MastershipTermService ts = mgr.requestTermService();
//term = 0 for both
mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
......
......@@ -11,6 +11,8 @@ import org.onlab.onos.cluster.ClusterService;
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.DefaultControllerNode;
import org.onlab.onos.cluster.MastershipServiceAdapter;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.MastershipTermService;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.cluster.ControllerNode.State;
import org.onlab.onos.event.Event;
......@@ -30,8 +32,6 @@ import org.onlab.onos.net.device.DeviceProvider;
import org.onlab.onos.net.device.DeviceProviderRegistry;
import org.onlab.onos.net.device.DeviceProviderService;
import org.onlab.onos.net.device.DeviceService;
import org.onlab.onos.net.device.DeviceMastershipTerm;
import org.onlab.onos.net.device.DeviceMastershipTermService;
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
......@@ -290,12 +290,12 @@ public class DeviceManagerTest {
}
@Override
public DeviceMastershipTermService requestTermService() {
return new DeviceMastershipTermService() {
public MastershipTermService requestTermService() {
return new MastershipTermService() {
@Override
public DeviceMastershipTerm getMastershipTerm(DeviceId deviceId) {
public MastershipTerm getMastershipTerm(DeviceId deviceId) {
// FIXME: just returning something not null
return DeviceMastershipTerm.of(NID_LOCAL, 1);
return MastershipTerm.of(NID_LOCAL, 1);
}
};
}
......@@ -339,7 +339,7 @@ public class DeviceManagerTest {
ClockProviderService {
@Override
public void setMastershipTerm(DeviceId deviceId, DeviceMastershipTerm term) {
public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
// TODO Auto-generated method stub
}
}
......
......@@ -58,8 +58,6 @@ public class HostManagerTest {
private static final IpPrefix IP1 = IpPrefix.valueOf("10.0.0.1");
private static final IpPrefix IP2 = IpPrefix.valueOf("10.0.0.2");
private static final Set<IpPrefix> IPSET1 = Sets.newHashSet(IP1);
private static final Set<IpPrefix> IPSET2 = Sets.newHashSet(IP2);
private static final DeviceId DID1 = DeviceId.deviceId("of:001");
private static final DeviceId DID2 = DeviceId.deviceId("of:002");
......@@ -94,14 +92,14 @@ public class HostManagerTest {
provider = new TestHostProvider();
providerService = registry.register(provider);
assertTrue("provider should be registered",
registry.getProviders().contains(provider.id()));
registry.getProviders().contains(provider.id()));
}
@After
public void tearDown() {
registry.unregister(provider);
assertFalse("provider should not be registered",
registry.getProviders().contains(provider.id()));
registry.getProviders().contains(provider.id()));
mgr.removeListener(listener);
mgr.deactivate();
......@@ -109,8 +107,8 @@ public class HostManagerTest {
}
private void detect(HostId hid, MacAddress mac, VlanId vlan,
HostLocation loc, Set<IpPrefix> ips) {
HostDescription descr = new DefaultHostDescription(mac, vlan, loc, ips);
HostLocation loc, IpPrefix ip) {
HostDescription descr = new DefaultHostDescription(mac, vlan, loc, ip);
providerService.hostDetected(hid, descr);
assertNotNull("host should be found", mgr.getHost(hid));
}
......@@ -130,26 +128,26 @@ public class HostManagerTest {
assertNull("host shouldn't be found", mgr.getHost(HID1));
// host addition
detect(HID1, MAC1, VLAN1, LOC1, IPSET1);
detect(HID1, MAC1, VLAN1, LOC1, IP1);
assertEquals("exactly one should be found", 1, mgr.getHostCount());
detect(HID2, MAC2, VLAN2, LOC2, IPSET1);
detect(HID2, MAC2, VLAN2, LOC2, IP1);
assertEquals("two hosts should be found", 2, mgr.getHostCount());
validateEvents(HOST_ADDED, HOST_ADDED);
// host motion
detect(HID1, MAC1, VLAN1, LOC2, IPSET1);
detect(HID1, MAC1, VLAN1, LOC2, IP1);
validateEvents(HOST_MOVED);
assertEquals("only two hosts should be found", 2, mgr.getHostCount());
// host update
detect(HID1, MAC1, VLAN1, LOC2, IPSET2);
detect(HID1, MAC1, VLAN1, LOC2, IP2);
validateEvents(HOST_UPDATED);
assertEquals("only two hosts should be found", 2, mgr.getHostCount());
}
@Test
public void hostVanished() {
detect(HID1, MAC1, VLAN1, LOC1, IPSET1);
detect(HID1, MAC1, VLAN1, LOC1, IP1);
providerService.hostVanished(HID1);
validateEvents(HOST_ADDED, HOST_REMOVED);
......@@ -157,7 +155,7 @@ public class HostManagerTest {
}
private void validateHosts(
String msg, Iterable<Host> hosts, HostId ... ids) {
String msg, Iterable<Host> hosts, HostId... ids) {
Set<HostId> hids = Sets.newHashSet(ids);
for (Host h : hosts) {
assertTrue(msg, hids.remove(h.id()));
......@@ -167,8 +165,8 @@ public class HostManagerTest {
@Test
public void getHosts() {
detect(HID1, MAC1, VLAN1, LOC1, IPSET1);
detect(HID2, MAC2, VLAN1, LOC2, IPSET2);
detect(HID1, MAC1, VLAN1, LOC1, IP1);
detect(HID2, MAC2, VLAN1, LOC2, IP2);
validateHosts("host not properly stored", mgr.getHosts(), HID1, HID2);
validateHosts("can't get hosts by VLAN", mgr.getHostsByVlan(VLAN1), HID1, HID2);
......@@ -210,7 +208,7 @@ public class HostManagerTest {
@Test
public void bindAddressesToPort() {
PortAddresses add1 = new PortAddresses(CP1,
Sets.newHashSet(PREFIX1, PREFIX2), MAC1);
Sets.newHashSet(PREFIX1, PREFIX2), MAC1);
mgr.bindAddressesToPort(add1);
PortAddresses storedAddresses = mgr.getAddressBindingsForPort(CP1);
......@@ -241,7 +239,7 @@ public class HostManagerTest {
@Test
public void unbindAddressesFromPort() {
PortAddresses add1 = new PortAddresses(CP1,
Sets.newHashSet(PREFIX1, PREFIX2), MAC1);
Sets.newHashSet(PREFIX1, PREFIX2), MAC1);
mgr.bindAddressesToPort(add1);
PortAddresses storedAddresses = mgr.getAddressBindingsForPort(CP1);
......@@ -250,7 +248,7 @@ public class HostManagerTest {
assertNotNull(storedAddresses.mac());
PortAddresses rem1 = new PortAddresses(CP1,
Sets.newHashSet(PREFIX1), null);
Sets.newHashSet(PREFIX1), null);
mgr.unbindAddressesFromPort(rem1);
storedAddresses = mgr.getAddressBindingsForPort(CP1);
......@@ -267,7 +265,7 @@ public class HostManagerTest {
assertNull(storedAddresses.mac());
PortAddresses rem3 = new PortAddresses(CP1,
Sets.newHashSet(PREFIX2), MAC1);
Sets.newHashSet(PREFIX2), MAC1);
mgr.unbindAddressesFromPort(rem3);
storedAddresses = mgr.getAddressBindingsForPort(CP1);
......@@ -279,7 +277,7 @@ public class HostManagerTest {
@Test
public void clearAddresses() {
PortAddresses add1 = new PortAddresses(CP1,
Sets.newHashSet(PREFIX1, PREFIX2), MAC1);
Sets.newHashSet(PREFIX1, PREFIX2), MAC1);
mgr.bindAddressesToPort(add1);
PortAddresses storedAddresses = mgr.getAddressBindingsForPort(CP1);
......@@ -297,7 +295,7 @@ public class HostManagerTest {
@Test
public void getAddressBindingsForPort() {
PortAddresses add1 = new PortAddresses(CP1,
Sets.newHashSet(PREFIX1, PREFIX2), MAC1);
Sets.newHashSet(PREFIX1, PREFIX2), MAC1);
mgr.bindAddressesToPort(add1);
PortAddresses storedAddresses = mgr.getAddressBindingsForPort(CP1);
......@@ -314,7 +312,7 @@ public class HostManagerTest {
assertTrue(storedAddresses.isEmpty());
PortAddresses add1 = new PortAddresses(CP1,
Sets.newHashSet(PREFIX1, PREFIX2), MAC1);
Sets.newHashSet(PREFIX1, PREFIX2), MAC1);
mgr.bindAddressesToPort(add1);
......@@ -323,7 +321,7 @@ public class HostManagerTest {
assertTrue(storedAddresses.size() == 1);
PortAddresses add2 = new PortAddresses(CP2,
Sets.newHashSet(PREFIX3), MAC2);
Sets.newHashSet(PREFIX3), MAC2);
mgr.bindAddressesToPort(add2);
......
......@@ -65,47 +65,48 @@ public class PathManagerTest {
@Test
public void infraToEdge() {
DeviceId src = did("src");
HostId dst = hid("dst");
HostId dst = hid("12:34:56:78:90:ab/1");
fakeTopoMgr.paths.add(createPath("src", "middle", "edge"));
fakeHostMgr.hosts.put(dst, host("dst", "edge"));
fakeHostMgr.hosts.put(dst, host("12:34:56:78:90:ab/1", "edge"));
Set<Path> paths = service.getPaths(src, dst);
validatePaths(paths, 1, 3, src, dst);
}
@Test
public void edgeToInfra() {
HostId src = hid("src");
HostId src = hid("12:34:56:78:90:ab/1");
DeviceId dst = did("dst");
fakeTopoMgr.paths.add(createPath("edge", "middle", "dst"));
fakeHostMgr.hosts.put(src, host("src", "edge"));
fakeHostMgr.hosts.put(src, host("12:34:56:78:90:ab/1", "edge"));
Set<Path> paths = service.getPaths(src, dst);
validatePaths(paths, 1, 3, src, dst);
}
@Test
public void edgeToEdge() {
HostId src = hid("src");
HostId dst = hid("dst");
HostId src = hid("12:34:56:78:90:ab/1");
HostId dst = hid("12:34:56:78:90:ef/1");
fakeTopoMgr.paths.add(createPath("srcEdge", "middle", "dstEdge"));
fakeHostMgr.hosts.put(src, host("src", "srcEdge"));
fakeHostMgr.hosts.put(dst, host("dst", "dstEdge"));
fakeHostMgr.hosts.put(src, host("12:34:56:78:90:ab/1", "srcEdge"));
fakeHostMgr.hosts.put(dst, host("12:34:56:78:90:ef/1", "dstEdge"));
Set<Path> paths = service.getPaths(src, dst);
validatePaths(paths, 1, 4, src, dst);
}
@Test
public void edgeToEdgeDirect() {
HostId src = hid("src");
HostId dst = hid("dst");
fakeHostMgr.hosts.put(src, host("src", "edge"));
fakeHostMgr.hosts.put(dst, host("dst", "edge"));
HostId src = hid("12:34:56:78:90:ab/1");
HostId dst = hid("12:34:56:78:90:ef/1");
fakeHostMgr.hosts.put(src, host("12:34:56:78:90:ab/1", "edge"));
fakeHostMgr.hosts.put(dst, host("12:34:56:78:90:ef/1", "edge"));
Set<Path> paths = service.getPaths(src, dst);
validatePaths(paths, 1, 2, src, dst);
}
@Test
public void noEdge() {
Set<Path> paths = service.getPaths(hid("src"), hid("dst"));
Set<Path> paths = service.getPaths(hid("12:34:56:78:90:ab/1"),
hid("12:34:56:78:90:ef/1"));
assertTrue("there should be no paths", paths.isEmpty());
}
......
......@@ -134,11 +134,11 @@ public class TopologyManagerTest {
service.isInfrastructure(topology, new ConnectPoint(did("a"), portNumber(3))));
// One of these cannot be a broadcast point... or we have a loop...
assertFalse("should not be broadcast point",
service.isBroadcastPoint(topology, new ConnectPoint(did("a"), portNumber(1))) &&
service.isBroadcastPoint(topology, new ConnectPoint(did("b"), portNumber(1))) &&
service.isBroadcastPoint(topology, new ConnectPoint(did("c"), portNumber(1))) &&
service.isBroadcastPoint(topology, new ConnectPoint(did("d"), portNumber(1))));
// assertFalse("should not be broadcast point",
// service.isBroadcastPoint(topology, new ConnectPoint(did("a"), portNumber(1))) &&
// service.isBroadcastPoint(topology, new ConnectPoint(did("b"), portNumber(1))) &&
// service.isBroadcastPoint(topology, new ConnectPoint(did("c"), portNumber(1))) &&
// service.isBroadcastPoint(topology, new ConnectPoint(did("d"), portNumber(1))));
assertTrue("should be broadcast point",
service.isBroadcastPoint(topology, new ConnectPoint(did("a"), portNumber(3))));
}
......
......@@ -54,8 +54,13 @@
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
<dependency>
<groupId>de.javakaffee</groupId>
<artifactId>kryo-serializers</artifactId>
<groupId>com.google.guava</groupId>
<artifactId>guava-testlib</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
......
......@@ -6,7 +6,6 @@ import java.io.IOException;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
......@@ -24,8 +23,10 @@ import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
import org.onlab.onos.store.cluster.messaging.ClusterMessage;
import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler;
import org.onlab.onos.store.cluster.messaging.MessageSubject;
import org.onlab.onos.store.serializers.ClusterMessageSerializer;
import org.onlab.onos.store.serializers.KryoPoolUtil;
import org.onlab.onos.store.serializers.KryoSerializer;
import org.onlab.onos.store.serializers.MessageSubjectSerializer;
import org.onlab.util.KryoPool;
import org.onlab.netty.Endpoint;
import org.onlab.netty.Message;
......
package org.onlab.onos.store.common.impl;
import java.util.Map;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.store.Timestamp;
import com.google.common.collect.ImmutableMap;
/**
* Anti-Entropy advertisement message.
* <p>
* Message to advertise the information this node holds.
*
* @param <ID> ID type
*/
public class AntiEntropyAdvertisement<ID> {
private final NodeId sender;
private final ImmutableMap<ID, Timestamp> advertisement;
/**
* Creates anti-entropy advertisement message.
*
* @param sender sender of this message
* @param advertisement timestamp information of the data sender holds
*/
public AntiEntropyAdvertisement(NodeId sender, Map<ID, Timestamp> advertisement) {
this.sender = sender;
this.advertisement = ImmutableMap.copyOf(advertisement);
}
public NodeId sender() {
return sender;
}
public ImmutableMap<ID, Timestamp> advertisement() {
return advertisement;
}
// Default constructor for serializer
protected AntiEntropyAdvertisement() {
this.sender = null;
this.advertisement = null;
}
}
package org.onlab.onos.store.common.impl;
import java.util.Map;
import java.util.Set;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.store.VersionedValue;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
/**
* Anti-Entropy reply message.
* <p>
* Message to send in reply to advertisement or another reply.
* Suggest to the sender about the more up-to-date data this node has,
* and request for more recent data that the receiver has.
*/
public class AntiEntropyReply<ID, V extends VersionedValue<?>> {
private final NodeId sender;
private final ImmutableMap<ID, V> suggestion;
private final ImmutableSet<ID> request;
/**
* Creates a reply to anti-entropy message.
*
* @param sender sender of this message
* @param suggestion collection of more recent values, sender had
* @param request Collection of identifiers
*/
public AntiEntropyReply(NodeId sender,
Map<ID, V> suggestion,
Set<ID> request) {
this.sender = sender;
this.suggestion = ImmutableMap.copyOf(suggestion);
this.request = ImmutableSet.copyOf(request);
}
public NodeId sender() {
return sender;
}
/**
* Returns collection of values, which the recipient of this reply is likely
* to be missing or has outdated version.
*
* @return
*/
public ImmutableMap<ID, V> suggestion() {
return suggestion;
}
/**
* Returns collection of identifier to request.
*
* @return collection of identifier to request
*/
public ImmutableSet<ID> request() {
return request;
}
/**
* Checks if reply contains any suggestion or request.
*
* @return true if nothing is suggested and requested
*/
public boolean isEmpty() {
return suggestion.isEmpty() && request.isEmpty();
}
// Default constructor for serializer
protected AntiEntropyReply() {
this.sender = null;
this.suggestion = null;
this.request = null;
}
}
package org.onlab.onos.store.common.impl;
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.NodeId;
import com.google.common.base.Function;
/**
* Function to convert ControllerNode to NodeId.
*/
public final class ControllerNodeToNodeId
implements Function<ControllerNode, NodeId> {
private static final ControllerNodeToNodeId INSTANCE = new ControllerNodeToNodeId();
@Override
public NodeId apply(ControllerNode input) {
return input.id();
}
public static ControllerNodeToNodeId toNodeId() {
return INSTANCE;
}
}
......@@ -13,7 +13,7 @@ import com.google.common.collect.ComparisonChain;
* Default implementation of Timestamp.
* TODO: Better documentation.
*/
public final class DeviceMastershipBasedTimestamp implements Timestamp {
public final class MastershipBasedTimestamp implements Timestamp {
private final int termNumber;
private final int sequenceNumber;
......@@ -24,16 +24,16 @@ public final class DeviceMastershipBasedTimestamp implements Timestamp {
* @param termNumber the mastership termNumber
* @param sequenceNumber the sequenceNumber number within the termNumber
*/
public DeviceMastershipBasedTimestamp(int termNumber, int sequenceNumber) {
public MastershipBasedTimestamp(int termNumber, int sequenceNumber) {
this.termNumber = termNumber;
this.sequenceNumber = sequenceNumber;
}
@Override
public int compareTo(Timestamp o) {
checkArgument(o instanceof DeviceMastershipBasedTimestamp,
checkArgument(o instanceof MastershipBasedTimestamp,
"Must be MastershipBasedTimestamp", o);
DeviceMastershipBasedTimestamp that = (DeviceMastershipBasedTimestamp) o;
MastershipBasedTimestamp that = (MastershipBasedTimestamp) o;
return ComparisonChain.start()
.compare(this.termNumber, that.termNumber)
......@@ -51,10 +51,10 @@ public final class DeviceMastershipBasedTimestamp implements Timestamp {
if (this == obj) {
return true;
}
if (!(obj instanceof DeviceMastershipBasedTimestamp)) {
if (!(obj instanceof MastershipBasedTimestamp)) {
return false;
}
DeviceMastershipBasedTimestamp that = (DeviceMastershipBasedTimestamp) obj;
MastershipBasedTimestamp that = (MastershipBasedTimestamp) obj;
return Objects.equals(this.termNumber, that.termNumber) &&
Objects.equals(this.sequenceNumber, that.sequenceNumber);
}
......@@ -87,7 +87,7 @@ public final class DeviceMastershipBasedTimestamp implements Timestamp {
// Default constructor for serialization
@Deprecated
protected DeviceMastershipBasedTimestamp() {
protected MastershipBasedTimestamp() {
this.termNumber = -1;
this.sequenceNumber = -1;
}
......
package org.onlab.onos.store;
package org.onlab.onos.store.common.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Objects;
import org.onlab.onos.store.Timestamp;
import com.google.common.base.MoreObjects;
/**
......@@ -28,6 +30,7 @@ public final class Timestamped<T> {
/**
* Returns the value.
*
* @return value
*/
public T value() {
......@@ -36,6 +39,7 @@ public final class Timestamped<T> {
/**
* Returns the time stamp.
*
* @return time stamp
*/
public Timestamp timestamp() {
......@@ -49,7 +53,16 @@ public final class Timestamped<T> {
* @return true if this instance is newer.
*/
public boolean isNewer(Timestamped<T> other) {
return this.timestamp.compareTo(checkNotNull(other).timestamp()) > 0;
return isNewer(checkNotNull(other).timestamp());
}
/**
* Tests if this timestamp is newer thatn the specified timestamp.
* @param timestamp to compare agains
* @return true if this instance is newer
*/
public boolean isNewer(Timestamp timestamp) {
return this.timestamp.compareTo(checkNotNull(timestamp)) > 0;
}
@Override
......
package org.onlab.onos.store.device.impl;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.Device;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.store.Timestamp;
import org.onlab.onos.store.VersionedValue;
import org.onlab.onos.store.common.impl.AntiEntropyAdvertisement;
// TODO DeviceID needs to be changed to something like (ProviderID, DeviceID)
// TODO: Handle Port as part of these messages, or separate messages for Ports?
public class DeviceAntiEntropyAdvertisement
extends AntiEntropyAdvertisement<DeviceId> {
public DeviceAntiEntropyAdvertisement(NodeId sender,
Map<DeviceId, Timestamp> advertisement) {
super(sender, advertisement);
}
// May need to add ProviderID, etc.
public static DeviceAntiEntropyAdvertisement create(
NodeId self,
Collection<VersionedValue<Device>> localValues) {
Map<DeviceId, Timestamp> ads = new HashMap<>(localValues.size());
for (VersionedValue<Device> e : localValues) {
ads.put(e.entity().id(), e.timestamp());
}
return new DeviceAntiEntropyAdvertisement(self, ads);
}
// For serializer
protected DeviceAntiEntropyAdvertisement() {}
}
package org.onlab.onos.store.device.impl;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.Device;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.store.Timestamp;
import org.onlab.onos.store.VersionedValue;
import org.onlab.onos.store.common.impl.AntiEntropyReply;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
public class DeviceAntiEntropyReply
extends AntiEntropyReply<DeviceId, VersionedValue<Device>> {
public DeviceAntiEntropyReply(NodeId sender,
Map<DeviceId, VersionedValue<Device>> suggestion,
Set<DeviceId> request) {
super(sender, suggestion, request);
}
/**
* Creates a reply to Anti-Entropy advertisement.
*
* @param advertisement to respond to
* @param self node identifier representing local node
* @param localValues local values held on this node
* @return reply message
*/
public static DeviceAntiEntropyReply reply(
DeviceAntiEntropyAdvertisement advertisement,
NodeId self,
Collection<VersionedValue<Device>> localValues
) {
ImmutableMap<DeviceId, Timestamp> ads = advertisement.advertisement();
ImmutableMap.Builder<DeviceId, VersionedValue<Device>>
sug = ImmutableMap.builder();
Set<DeviceId> req = new HashSet<>(ads.keySet());
for (VersionedValue<Device> e : localValues) {
final DeviceId id = e.entity().id();
final Timestamp local = e.timestamp();
final Timestamp theirs = ads.get(id);
if (theirs == null) {
// they don't have it, suggest
sug.put(id, e);
// don't need theirs
req.remove(id);
} else if (local.compareTo(theirs) < 0) {
// they got older one, suggest
sug.put(id, e);
// don't need theirs
req.remove(id);
} else if (local.equals(theirs)) {
// same, don't need theirs
req.remove(id);
}
}
return new DeviceAntiEntropyReply(self, sug.build(), req);
}
/**
* Creates a reply to request for values held locally.
*
* @param requests message containing the request
* @param self node identifier representing local node
* @param localValues local valeds held on this node
* @return reply message
*/
public static DeviceAntiEntropyReply reply(
DeviceAntiEntropyReply requests,
NodeId self,
Map<DeviceId, VersionedValue<Device>> localValues
) {
Set<DeviceId> reqs = requests.request();
Map<DeviceId, VersionedValue<Device>> requested = new HashMap<>(reqs.size());
for (DeviceId id : reqs) {
final VersionedValue<Device> value = localValues.get(id);
if (value != null) {
requested.put(id, value);
}
}
Set<DeviceId> empty = ImmutableSet.of();
return new DeviceAntiEntropyReply(self, requested, empty);
}
// For serializer
protected DeviceAntiEntropyReply() {}
}
......@@ -10,12 +10,12 @@ import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.DeviceMastershipTerm;
import org.onlab.onos.store.ClockProviderService;
import org.onlab.onos.store.ClockService;
import org.onlab.onos.store.Timestamp;
import org.onlab.onos.store.common.impl.DeviceMastershipBasedTimestamp;
import org.onlab.onos.store.common.impl.MastershipBasedTimestamp;
import org.slf4j.Logger;
/**
......@@ -29,7 +29,7 @@ public class DeviceClockManager implements ClockService, ClockProviderService {
// TODO: Implement per device ticker that is reset to 0 at the beginning of a new term.
private final AtomicInteger ticker = new AtomicInteger(0);
private ConcurrentMap<DeviceId, DeviceMastershipTerm> deviceMastershipTerms = new ConcurrentHashMap<>();
private ConcurrentMap<DeviceId, MastershipTerm> deviceMastershipTerms = new ConcurrentHashMap<>();
@Activate
public void activate() {
......@@ -43,15 +43,15 @@ public class DeviceClockManager implements ClockService, ClockProviderService {
@Override
public Timestamp getTimestamp(DeviceId deviceId) {
DeviceMastershipTerm term = deviceMastershipTerms.get(deviceId);
MastershipTerm term = deviceMastershipTerms.get(deviceId);
if (term == null) {
throw new IllegalStateException("Requesting timestamp for a deviceId without mastership");
}
return new DeviceMastershipBasedTimestamp(term.termNumber(), ticker.incrementAndGet());
return new MastershipBasedTimestamp(term.termNumber(), ticker.incrementAndGet());
}
@Override
public void setMastershipTerm(DeviceId deviceId, DeviceMastershipTerm term) {
public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
deviceMastershipTerms.put(deviceId, term);
}
}
......
package org.onlab.onos.store.device.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.onos.net.DefaultAnnotations.union;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.SparseAnnotations;
import org.onlab.onos.net.device.DefaultDeviceDescription;
import org.onlab.onos.net.device.DefaultPortDescription;
import org.onlab.onos.net.device.DeviceDescription;
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.store.Timestamp;
import org.onlab.onos.store.common.impl.Timestamped;
/*
* Collection of Description of a Device and Ports, given from a Provider.
*/
class DeviceDescriptions {
private volatile Timestamped<DeviceDescription> deviceDesc;
private final ConcurrentMap<PortNumber, Timestamped<PortDescription>> portDescs;
public DeviceDescriptions(Timestamped<DeviceDescription> desc) {
this.deviceDesc = checkNotNull(desc);
this.portDescs = new ConcurrentHashMap<>();
}
public Timestamp getLatestTimestamp() {
Timestamp latest = deviceDesc.timestamp();
for (Timestamped<PortDescription> desc : portDescs.values()) {
if (desc.timestamp().compareTo(latest) > 0) {
latest = desc.timestamp();
}
}
return latest;
}
public Timestamped<DeviceDescription> getDeviceDesc() {
return deviceDesc;
}
public Timestamped<PortDescription> getPortDesc(PortNumber number) {
return portDescs.get(number);
}
public Map<PortNumber, Timestamped<PortDescription>> getPortDescs() {
return Collections.unmodifiableMap(portDescs);
}
/**
* Puts DeviceDescription, merging annotations as necessary.
*
* @param newDesc new DeviceDescription
*/
public synchronized void putDeviceDesc(Timestamped<DeviceDescription> newDesc) {
Timestamped<DeviceDescription> oldOne = deviceDesc;
Timestamped<DeviceDescription> newOne = newDesc;
if (oldOne != null) {
SparseAnnotations merged = union(oldOne.value().annotations(),
newDesc.value().annotations());
newOne = new Timestamped<DeviceDescription>(
new DefaultDeviceDescription(newDesc.value(), merged),
newDesc.timestamp());
}
deviceDesc = newOne;
}
/**
* Puts PortDescription, merging annotations as necessary.
*
* @param newDesc new PortDescription
*/
public synchronized void putPortDesc(Timestamped<PortDescription> newDesc) {
Timestamped<PortDescription> oldOne = portDescs.get(newDesc.value().portNumber());
Timestamped<PortDescription> newOne = newDesc;
if (oldOne != null) {
SparseAnnotations merged = union(oldOne.value().annotations(),
newDesc.value().annotations());
newOne = new Timestamped<PortDescription>(
new DefaultPortDescription(newDesc.value(), merged),
newDesc.timestamp());
}
portDescs.put(newOne.value().portNumber(), newOne);
}
}
......@@ -5,8 +5,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.concurrent.ConcurrentException;
import org.apache.commons.lang3.concurrent.ConcurrentInitializer;
import org.apache.commons.lang3.RandomUtils;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
......@@ -14,6 +13,8 @@ import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.cluster.ClusterService;
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.AnnotationsUtil;
import org.onlab.onos.net.DefaultAnnotations;
import org.onlab.onos.net.DefaultDevice;
......@@ -23,9 +24,6 @@ import org.onlab.onos.net.Device.Type;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Port;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.SparseAnnotations;
import org.onlab.onos.net.device.DefaultDeviceDescription;
import org.onlab.onos.net.device.DefaultPortDescription;
import org.onlab.onos.net.device.DeviceDescription;
import org.onlab.onos.net.device.DeviceEvent;
import org.onlab.onos.net.device.DeviceStore;
......@@ -35,21 +33,25 @@ import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.AbstractStore;
import org.onlab.onos.store.ClockService;
import org.onlab.onos.store.Timestamp;
import org.onlab.onos.store.Timestamped;
import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
import org.onlab.onos.store.cluster.messaging.ClusterMessage;
import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler;
import org.onlab.onos.store.common.impl.DeviceMastershipBasedTimestamp;
import org.onlab.onos.store.common.impl.MastershipBasedTimestampSerializer;
import org.onlab.onos.store.serializers.KryoPoolUtil;
import org.onlab.onos.store.cluster.messaging.MessageSubject;
import org.onlab.onos.store.common.impl.Timestamped;
import org.onlab.onos.store.device.impl.peermsg.DeviceAntiEntropyAdvertisement;
import org.onlab.onos.store.device.impl.peermsg.DeviceFragmentId;
import org.onlab.onos.store.device.impl.peermsg.PortFragmentId;
import org.onlab.onos.store.serializers.KryoSerializer;
import org.onlab.onos.store.serializers.DistributedStoreSerializers;
import org.onlab.util.KryoPool;
import org.onlab.util.NewConcurrentHashMap;
import org.slf4j.Logger;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
......@@ -57,19 +59,21 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.notNull;
import static org.onlab.onos.net.device.DeviceEvent.Type.*;
import static org.slf4j.LoggerFactory.getLogger;
import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked;
import static org.onlab.onos.net.DefaultAnnotations.merge;
import static org.onlab.onos.net.DefaultAnnotations.union;
import static com.google.common.base.Verify.verify;
import static org.onlab.util.Tools.namedThreads;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.onos.store.device.impl.GossipDeviceStoreMessageSubjects.DEVICE_ADVERTISE;
import static org.onlab.onos.store.common.impl.ControllerNodeToNodeId.toNodeId;
// TODO: give me a better name
/**
......@@ -86,8 +90,9 @@ public class GossipDeviceStore
public static final String DEVICE_NOT_FOUND = "Device with ID %s not found";
// TODO: Check if inner Map can be replaced with plain Map
// TODO: Check if inner Map can be replaced with plain Map.
// innerMap is used to lock a Device, thus instance should never be replaced.
// collection of Description given from various providers
private final ConcurrentMap<DeviceId,
ConcurrentMap<ProviderId, DeviceDescriptions>>
......@@ -117,21 +122,23 @@ public class GossipDeviceStore
@Override
protected void setupKryoPool() {
serializerPool = KryoPool.newBuilder()
.register(KryoPoolUtil.API)
.register(DistributedStoreSerializers.COMMON)
.register(InternalDeviceEvent.class, new InternalDeviceEventSerializer())
.register(InternalDeviceOfflineEvent.class, new InternalDeviceOfflineEventSerializer())
.register(InternalDeviceRemovedEvent.class)
.register(InternalPortEvent.class, new InternalPortEventSerializer())
.register(InternalPortStatusEvent.class, new InternalPortStatusEventSerializer())
.register(Timestamp.class)
.register(Timestamped.class)
.register(DeviceMastershipBasedTimestamp.class, new MastershipBasedTimestampSerializer())
.register(DeviceAntiEntropyAdvertisement.class)
.register(DeviceFragmentId.class)
.register(PortFragmentId.class)
.build()
.populate(1);
}
};
private ScheduledExecutorService executor;
@Activate
public void activate() {
clusterCommunicator.addSubscriber(
......@@ -144,11 +151,35 @@ public class GossipDeviceStore
GossipDeviceStoreMessageSubjects.PORT_UPDATE, new InternalPortEventListener());
clusterCommunicator.addSubscriber(
GossipDeviceStoreMessageSubjects.PORT_STATUS_UPDATE, new InternalPortStatusEventListener());
clusterCommunicator.addSubscriber(
GossipDeviceStoreMessageSubjects.DEVICE_ADVERTISE, new InternalDeviceAdvertisementListener());
executor =
newSingleThreadScheduledExecutor(namedThreads("anti-entropy-%d"));
// TODO: Make these configurable
long initialDelaySec = 5;
long periodSec = 5;
// start anti-entropy thread
executor.scheduleAtFixedRate(new SendAdvertisementTask(),
initialDelaySec, periodSec, TimeUnit.SECONDS);
log.info("Started");
}
@Deactivate
public void deactivate() {
executor.shutdownNow();
try {
boolean timedout = executor.awaitTermination(5, TimeUnit.SECONDS);
if (timedout) {
log.error("Timeout during executor shutdown");
}
} catch (InterruptedException e) {
log.error("Error during executor shutdown", e);
}
deviceDescs.clear();
devices.clear();
devicePorts.clear();
......@@ -543,14 +574,14 @@ public class GossipDeviceStore
final Timestamped<PortDescription> existingPortDesc = descs.getPortDesc(number);
if (existingPortDesc == null ||
deltaDesc == existingPortDesc ||
deltaDesc.isNewer(existingPortDesc)) {
// on new port or valid update
// update description
descs.putPortDesc(deltaDesc);
newPort = composePort(device, number, descsMap);
} else {
// outdated event, ignored.
// same or outdated event, ignored.
log.trace("ignore same or outdated {} >= {}", existingPortDesc, deltaDesc);
return null;
}
......@@ -627,6 +658,14 @@ public class GossipDeviceStore
}
}
/**
* Checks if given timestamp is superseded by removal request
* with more recent timestamp.
*
* @param deviceId identifier of a device
* @param timestampToCheck timestamp of an event to check
* @return true if device is already removed
*/
private boolean isDeviceRemoved(DeviceId deviceId, Timestamp timestampToCheck) {
Timestamp removalTimestamp = removalRequest.get(deviceId);
if (removalTimestamp != null &&
......@@ -667,7 +706,7 @@ public class GossipDeviceStore
continue;
}
// TODO: should keep track of Description timestamp
// and only merge conflicting keys when timestamp is newer
// and only merge conflicting keys when timestamp is newer.
// Currently assuming there will never be a key conflict between
// providers
......@@ -708,7 +747,7 @@ public class GossipDeviceStore
continue;
}
// TODO: should keep track of Description timestamp
// and only merge conflicting keys when timestamp is newer
// and only merge conflicting keys when timestamp is newer.
// Currently assuming there will never be a key conflict between
// providers
......@@ -745,129 +784,258 @@ public class GossipDeviceStore
return providerDescs.get(pid);
}
public static final class InitDeviceDescs
implements ConcurrentInitializer<DeviceDescriptions> {
// TODO: should we be throwing exception?
private void unicastMessage(NodeId recipient, MessageSubject subject, Object event) throws IOException {
ClusterMessage message = new ClusterMessage(
clusterService.getLocalNode().id(),
subject,
SERIALIZER.encode(event));
clusterCommunicator.unicast(message, recipient);
}
private final Timestamped<DeviceDescription> deviceDesc;
// TODO: should we be throwing exception?
private void broadcastMessage(MessageSubject subject, Object event) throws IOException {
ClusterMessage message = new ClusterMessage(
clusterService.getLocalNode().id(),
subject,
SERIALIZER.encode(event));
clusterCommunicator.broadcast(message);
}
public InitDeviceDescs(Timestamped<DeviceDescription> deviceDesc) {
this.deviceDesc = checkNotNull(deviceDesc);
}
@Override
public DeviceDescriptions get() throws ConcurrentException {
return new DeviceDescriptions(deviceDesc);
}
private void notifyPeers(InternalDeviceEvent event) throws IOException {
broadcastMessage(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE, event);
}
private void notifyPeers(InternalDeviceOfflineEvent event) throws IOException {
broadcastMessage(GossipDeviceStoreMessageSubjects.DEVICE_OFFLINE, event);
}
/**
* Collection of Description of a Device and it's Ports given from a Provider.
*/
public static class DeviceDescriptions {
private void notifyPeers(InternalDeviceRemovedEvent event) throws IOException {
broadcastMessage(GossipDeviceStoreMessageSubjects.DEVICE_REMOVED, event);
}
private final AtomicReference<Timestamped<DeviceDescription>> deviceDesc;
private final ConcurrentMap<PortNumber, Timestamped<PortDescription>> portDescs;
private void notifyPeers(InternalPortEvent event) throws IOException {
broadcastMessage(GossipDeviceStoreMessageSubjects.PORT_UPDATE, event);
}
public DeviceDescriptions(Timestamped<DeviceDescription> desc) {
this.deviceDesc = new AtomicReference<>(checkNotNull(desc));
this.portDescs = new ConcurrentHashMap<>();
}
private void notifyPeers(InternalPortStatusEvent event) throws IOException {
broadcastMessage(GossipDeviceStoreMessageSubjects.PORT_STATUS_UPDATE, event);
}
Timestamp getLatestTimestamp() {
Timestamp latest = deviceDesc.get().timestamp();
for (Timestamped<PortDescription> desc : portDescs.values()) {
if (desc.timestamp().compareTo(latest) > 0) {
latest = desc.timestamp();
}
}
return latest;
private void notifyPeer(NodeId recipient, InternalDeviceEvent event) {
try {
unicastMessage(recipient, GossipDeviceStoreMessageSubjects.DEVICE_UPDATE, event);
} catch (IOException e) {
log.error("Failed to send" + event + " to " + recipient, e);
}
}
public Timestamped<DeviceDescription> getDeviceDesc() {
return deviceDesc.get();
private void notifyPeer(NodeId recipient, InternalDeviceOfflineEvent event) {
try {
unicastMessage(recipient, GossipDeviceStoreMessageSubjects.DEVICE_OFFLINE, event);
} catch (IOException e) {
log.error("Failed to send" + event + " to " + recipient, e);
}
}
public Timestamped<PortDescription> getPortDesc(PortNumber number) {
return portDescs.get(number);
private void notifyPeer(NodeId recipient, InternalDeviceRemovedEvent event) {
try {
unicastMessage(recipient, GossipDeviceStoreMessageSubjects.DEVICE_REMOVED, event);
} catch (IOException e) {
log.error("Failed to send" + event + " to " + recipient, e);
}
}
/**
* Puts DeviceDescription, merging annotations as necessary.
*
* @param newDesc new DeviceDescription
* @return previous DeviceDescription
*/
public synchronized Timestamped<DeviceDescription> putDeviceDesc(Timestamped<DeviceDescription> newDesc) {
Timestamped<DeviceDescription> oldOne = deviceDesc.get();
Timestamped<DeviceDescription> newOne = newDesc;
if (oldOne != null) {
SparseAnnotations merged = union(oldOne.value().annotations(),
newDesc.value().annotations());
newOne = new Timestamped<DeviceDescription>(
new DefaultDeviceDescription(newDesc.value(), merged),
newDesc.timestamp());
}
return deviceDesc.getAndSet(newOne);
}
/**
* Puts PortDescription, merging annotations as necessary.
*
* @param newDesc new PortDescription
* @return previous PortDescription
*/
public synchronized Timestamped<PortDescription> putPortDesc(Timestamped<PortDescription> newDesc) {
Timestamped<PortDescription> oldOne = portDescs.get(newDesc.value().portNumber());
Timestamped<PortDescription> newOne = newDesc;
if (oldOne != null) {
SparseAnnotations merged = union(oldOne.value().annotations(),
newDesc.value().annotations());
newOne = new Timestamped<PortDescription>(
new DefaultPortDescription(newDesc.value(), merged),
newDesc.timestamp());
}
return portDescs.put(newOne.value().portNumber(), newOne);
private void notifyPeer(NodeId recipient, InternalPortEvent event) {
try {
unicastMessage(recipient, GossipDeviceStoreMessageSubjects.PORT_UPDATE, event);
} catch (IOException e) {
log.error("Failed to send" + event + " to " + recipient, e);
}
}
private void notifyPeers(InternalDeviceEvent event) throws IOException {
ClusterMessage message = new ClusterMessage(
clusterService.getLocalNode().id(),
GossipDeviceStoreMessageSubjects.DEVICE_UPDATE,
SERIALIZER.encode(event));
clusterCommunicator.broadcast(message);
private void notifyPeer(NodeId recipient, InternalPortStatusEvent event) {
try {
unicastMessage(recipient, GossipDeviceStoreMessageSubjects.PORT_STATUS_UPDATE, event);
} catch (IOException e) {
log.error("Failed to send" + event + " to " + recipient, e);
}
}
private void notifyPeers(InternalDeviceOfflineEvent event) throws IOException {
ClusterMessage message = new ClusterMessage(
clusterService.getLocalNode().id(),
GossipDeviceStoreMessageSubjects.DEVICE_OFFLINE,
SERIALIZER.encode(event));
clusterCommunicator.broadcast(message);
}
private DeviceAntiEntropyAdvertisement createAdvertisement() {
final NodeId self = clusterService.getLocalNode().id();
private void notifyPeers(InternalDeviceRemovedEvent event) throws IOException {
ClusterMessage message = new ClusterMessage(
clusterService.getLocalNode().id(),
GossipDeviceStoreMessageSubjects.DEVICE_REMOVED,
SERIALIZER.encode(event));
clusterCommunicator.broadcast(message);
}
Map<DeviceFragmentId, Timestamp> devices = new HashMap<>(deviceDescs.size());
final int portsPerDevice = 8; // random guess to minimize reallocation
Map<PortFragmentId, Timestamp> ports = new HashMap<>(devices.size() * portsPerDevice);
Map<DeviceId, Timestamp> offline = new HashMap<>(devices.size());
private void notifyPeers(InternalPortEvent event) throws IOException {
ClusterMessage message = new ClusterMessage(
clusterService.getLocalNode().id(),
GossipDeviceStoreMessageSubjects.PORT_UPDATE,
SERIALIZER.encode(event));
clusterCommunicator.broadcast(message);
for (Entry<DeviceId, ConcurrentMap<ProviderId, DeviceDescriptions>>
provs : deviceDescs.entrySet()) {
final DeviceId deviceId = provs.getKey();
final ConcurrentMap<ProviderId, DeviceDescriptions> devDescs = provs.getValue();
synchronized (devDescs) {
offline.put(deviceId, this.offline.get(deviceId));
for (Entry<ProviderId, DeviceDescriptions>
prov : devDescs.entrySet()) {
final ProviderId provId = prov.getKey();
final DeviceDescriptions descs = prov.getValue();
devices.put(new DeviceFragmentId(deviceId, provId),
descs.getDeviceDesc().timestamp());
for (Entry<PortNumber, Timestamped<PortDescription>>
portDesc : descs.getPortDescs().entrySet()) {
final PortNumber number = portDesc.getKey();
ports.put(new PortFragmentId(deviceId, provId, number),
portDesc.getValue().timestamp());
}
}
}
}
return new DeviceAntiEntropyAdvertisement(self, devices, ports, offline);
}
private void notifyPeers(InternalPortStatusEvent event) throws IOException {
ClusterMessage message = new ClusterMessage(
clusterService.getLocalNode().id(),
GossipDeviceStoreMessageSubjects.PORT_STATUS_UPDATE,
SERIALIZER.encode(event));
clusterCommunicator.broadcast(message);
/**
* Responds to anti-entropy advertisement message.
* <P>
* Notify sender about out-dated information using regular replication message.
* Send back advertisement to sender if not in sync.
*
* @param advertisement to respond to
*/
private void handleAdvertisement(DeviceAntiEntropyAdvertisement advertisement) {
final NodeId sender = advertisement.sender();
Map<DeviceFragmentId, Timestamp> devAds = new HashMap<>(advertisement.deviceFingerPrints());
Map<PortFragmentId, Timestamp> portAds = new HashMap<>(advertisement.ports());
Map<DeviceId, Timestamp> offlineAds = new HashMap<>(advertisement.offline());
// Fragments to request
Collection<DeviceFragmentId> reqDevices = new ArrayList<>();
Collection<PortFragmentId> reqPorts = new ArrayList<>();
for (Entry<DeviceId, ConcurrentMap<ProviderId, DeviceDescriptions>> de : deviceDescs.entrySet()) {
final DeviceId deviceId = de.getKey();
final Map<ProviderId, DeviceDescriptions> lDevice = de.getValue();
synchronized (lDevice) {
// latestTimestamp across provider
// Note: can be null initially
Timestamp localLatest = offline.get(deviceId);
// handle device Ads
for (Entry<ProviderId, DeviceDescriptions> prov : lDevice.entrySet()) {
final ProviderId provId = prov.getKey();
final DeviceDescriptions lDeviceDescs = prov.getValue();
final DeviceFragmentId devFragId = new DeviceFragmentId(deviceId, provId);
Timestamped<DeviceDescription> lProvDevice = lDeviceDescs.getDeviceDesc();
Timestamp advDevTimestamp = devAds.get(devFragId);
if (advDevTimestamp == null || lProvDevice.isNewer(advDevTimestamp)) {
// remote does not have it or outdated, suggest
notifyPeer(sender, new InternalDeviceEvent(provId, deviceId, lProvDevice));
} else if (!lProvDevice.timestamp().equals(advDevTimestamp)) {
// local is outdated, request
reqDevices.add(devFragId);
}
// handle port Ads
for (Entry<PortNumber, Timestamped<PortDescription>>
pe : lDeviceDescs.getPortDescs().entrySet()) {
final PortNumber num = pe.getKey();
final Timestamped<PortDescription> lPort = pe.getValue();
final PortFragmentId portFragId = new PortFragmentId(deviceId, provId, num);
Timestamp advPortTimestamp = portAds.get(portFragId);
if (advPortTimestamp == null || lPort.isNewer(advPortTimestamp)) {
// remote does not have it or outdated, suggest
notifyPeer(sender, new InternalPortStatusEvent(provId, deviceId, lPort));
} else if (!lPort.timestamp().equals(advPortTimestamp)) {
// local is outdated, request
log.trace("need update {} < {}", lPort.timestamp(), advPortTimestamp);
reqPorts.add(portFragId);
}
// remove port Ad already processed
portAds.remove(portFragId);
} // end local port loop
// remove device Ad already processed
devAds.remove(devFragId);
// find latest and update
final Timestamp providerLatest = lDeviceDescs.getLatestTimestamp();
if (localLatest == null ||
providerLatest.compareTo(localLatest) > 0) {
localLatest = providerLatest;
}
} // end local provider loop
// checking if remote timestamp is more recent.
Timestamp rOffline = offlineAds.get(deviceId);
if (rOffline != null &&
rOffline.compareTo(localLatest) > 0) {
// remote offline timestamp suggests that the
// device is off-line
markOfflineInternal(deviceId, rOffline);
}
Timestamp lOffline = offline.get(deviceId);
if (lOffline != null && rOffline == null) {
// locally offline, but remote is online, suggest offline
notifyPeer(sender, new InternalDeviceOfflineEvent(deviceId, lOffline));
}
// remove device offline Ad already processed
offlineAds.remove(deviceId);
} // end local device loop
} // device lock
// If there is any Ads left, request them
log.trace("Ads left {}, {}", devAds, portAds);
reqDevices.addAll(devAds.keySet());
reqPorts.addAll(portAds.keySet());
if (reqDevices.isEmpty() && reqPorts.isEmpty()) {
log.trace("Nothing to request to remote peer {}", sender);
return;
}
log.info("Need to sync {} {}", reqDevices, reqPorts);
// 2-way Anti-Entropy for now
try {
unicastMessage(sender, DEVICE_ADVERTISE, createAdvertisement());
} catch (IOException e) {
log.error("Failed to send response advertisement to " + sender, e);
}
// Sketch of 3-way Anti-Entropy
// DeviceAntiEntropyRequest request = new DeviceAntiEntropyRequest(self, reqDevices, reqPorts);
// ClusterMessage message = new ClusterMessage(
// clusterService.getLocalNode().id(),
// GossipDeviceStoreMessageSubjects.DEVICE_REQUEST,
// SERIALIZER.encode(request));
//
// try {
// clusterCommunicator.unicast(message, advertisement.sender());
// } catch (IOException e) {
// log.error("Failed to send advertisement reply to "
// + advertisement.sender(), e);
// }
}
private void notifyDelegateIfNotNull(DeviceEvent event) {
......@@ -876,6 +1044,54 @@ public class GossipDeviceStore
}
}
private final class SendAdvertisementTask implements Runnable {
@Override
public void run() {
if (Thread.currentThread().isInterrupted()) {
log.info("Interrupted, quitting");
return;
}
try {
final NodeId self = clusterService.getLocalNode().id();
Set<ControllerNode> nodes = clusterService.getNodes();
ImmutableList<NodeId> nodeIds = FluentIterable.from(nodes)
.transform(toNodeId())
.toList();
if (nodeIds.size() == 1 && nodeIds.get(0).equals(self)) {
log.info("No other peers in the cluster.");
return;
}
NodeId peer;
do {
int idx = RandomUtils.nextInt(0, nodeIds.size());
peer = nodeIds.get(idx);
} while (peer.equals(self));
DeviceAntiEntropyAdvertisement ad = createAdvertisement();
if (Thread.currentThread().isInterrupted()) {
log.info("Interrupted, quitting");
return;
}
try {
unicastMessage(peer, DEVICE_ADVERTISE, ad);
} catch (IOException e) {
log.error("Failed to send anti-entropy advertisement", e);
return;
}
} catch (Exception e) {
// catch all Exception to avoid Scheduled task being suppressed.
log.error("Exception thrown while sending advertisement", e);
}
}
}
private class InternalDeviceEventListener implements ClusterMessageHandler {
@Override
public void handle(ClusterMessage message) {
......@@ -940,6 +1156,7 @@ public class GossipDeviceStore
log.info("Received port status update event from peer: {}", message.sender());
InternalPortStatusEvent event = (InternalPortStatusEvent) SERIALIZER.decode(message.payload());
log.info("{}", event);
ProviderId providerId = event.providerId();
DeviceId deviceId = event.deviceId();
......@@ -948,4 +1165,15 @@ public class GossipDeviceStore
notifyDelegateIfNotNull(updatePortStatusInternal(providerId, deviceId, portDescription));
}
}
private final class InternalDeviceAdvertisementListener
implements ClusterMessageHandler {
@Override
public void handle(ClusterMessage message) {
log.info("Received Device advertisement from peer: {}", message.sender());
DeviceAntiEntropyAdvertisement advertisement = SERIALIZER.decode(message.payload());
handleAdvertisement(advertisement);
}
}
}
......
......@@ -2,6 +2,7 @@ package org.onlab.onos.store.device.impl;
import org.onlab.onos.store.cluster.messaging.MessageSubject;
// TODO: add prefix to assure uniqueness.
/**
* MessageSubjects used by GossipDeviceStore peer-peer communication.
*/
......@@ -14,4 +15,8 @@ public final class GossipDeviceStoreMessageSubjects {
public static final MessageSubject DEVICE_REMOVED = new MessageSubject("peer-device-removed");
public static final MessageSubject PORT_UPDATE = new MessageSubject("peer-port-update");
public static final MessageSubject PORT_STATUS_UPDATE = new MessageSubject("peer-port-status-update");
public static final MessageSubject DEVICE_ADVERTISE = new MessageSubject("peer-device-advertisements");
// to be used with 3-way anti-entropy process
public static final MessageSubject DEVICE_REQUEST = new MessageSubject("peer-device-request");
}
......
package org.onlab.onos.store.device.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import org.apache.commons.lang3.concurrent.ConcurrentException;
import org.apache.commons.lang3.concurrent.ConcurrentInitializer;
import org.onlab.onos.net.device.DeviceDescription;
import org.onlab.onos.store.common.impl.Timestamped;
// FIXME: consider removing this class
public final class InitDeviceDescs
implements ConcurrentInitializer<DeviceDescriptions> {
private final Timestamped<DeviceDescription> deviceDesc;
public InitDeviceDescs(Timestamped<DeviceDescription> deviceDesc) {
this.deviceDesc = checkNotNull(deviceDesc);
}
@Override
public DeviceDescriptions get() throws ConcurrentException {
return new DeviceDescriptions(deviceDesc);
}
}
\ No newline at end of file
......@@ -3,7 +3,9 @@ package org.onlab.onos.store.device.impl;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.DeviceDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.Timestamped;
import org.onlab.onos.store.common.impl.Timestamped;
import com.google.common.base.MoreObjects;
/**
* Information published by GossipDeviceStore to notify peers of a device
......@@ -36,6 +38,15 @@ public class InternalDeviceEvent {
return deviceDescription;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("providerId", providerId)
.add("deviceId", deviceId)
.add("deviceDescription", deviceDescription)
.toString();
}
// for serializer
protected InternalDeviceEvent() {
this.providerId = null;
......
......@@ -3,7 +3,7 @@ package org.onlab.onos.store.device.impl;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.DeviceDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.Timestamped;
import org.onlab.onos.store.common.impl.Timestamped;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
......
......@@ -3,6 +3,8 @@ package org.onlab.onos.store.device.impl;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.store.Timestamp;
import com.google.common.base.MoreObjects;
/**
* Information published by GossipDeviceStore to notify peers of a device
* going offline.
......@@ -30,6 +32,14 @@ public class InternalDeviceOfflineEvent {
return timestamp;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("deviceId", deviceId)
.add("timestamp", timestamp)
.toString();
}
// for serializer
@SuppressWarnings("unused")
private InternalDeviceOfflineEvent() {
......
......@@ -3,6 +3,8 @@ package org.onlab.onos.store.device.impl;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.store.Timestamp;
import com.google.common.base.MoreObjects;
/**
* Information published by GossipDeviceStore to notify peers of a device
* being administratively removed.
......@@ -30,6 +32,14 @@ public class InternalDeviceRemovedEvent {
return timestamp;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("deviceId", deviceId)
.add("timestamp", timestamp)
.toString();
}
// for serializer
@SuppressWarnings("unused")
private InternalDeviceRemovedEvent() {
......
......@@ -5,7 +5,9 @@ import java.util.List;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.Timestamped;
import org.onlab.onos.store.common.impl.Timestamped;
import com.google.common.base.MoreObjects;
/**
* Information published by GossipDeviceStore to notify peers of a port
......@@ -38,6 +40,15 @@ public class InternalPortEvent {
return portDescriptions;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("providerId", providerId)
.add("deviceId", deviceId)
.add("portDescriptions", portDescriptions)
.toString();
}
// for serializer
protected InternalPortEvent() {
this.providerId = null;
......
......@@ -5,7 +5,7 @@ import java.util.List;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.Timestamped;
import org.onlab.onos.store.common.impl.Timestamped;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
......
......@@ -3,7 +3,9 @@ package org.onlab.onos.store.device.impl;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.Timestamped;
import org.onlab.onos.store.common.impl.Timestamped;
import com.google.common.base.MoreObjects;
/**
* Information published by GossipDeviceStore to notify peers of a port
......@@ -36,6 +38,15 @@ public class InternalPortStatusEvent {
return portDescription;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("providerId", providerId)
.add("deviceId", deviceId)
.add("portDescription", portDescription)
.toString();
}
// for serializer
protected InternalPortStatusEvent() {
this.providerId = null;
......
......@@ -3,7 +3,7 @@ package org.onlab.onos.store.device.impl;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.Timestamped;
import org.onlab.onos.store.common.impl.Timestamped;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
......@@ -35,6 +35,7 @@ public class InternalPortStatusEventSerializer extends Serializer<InternalPortSt
Class<InternalPortStatusEvent> type) {
ProviderId providerId = (ProviderId) kryo.readClassAndObject(input);
DeviceId deviceId = (DeviceId) kryo.readClassAndObject(input);
@SuppressWarnings("unchecked")
Timestamped<PortDescription> portDescription = (Timestamped<PortDescription>) kryo.readClassAndObject(input);
return new InternalPortStatusEvent(providerId, deviceId, portDescription);
......
package org.onlab.onos.store.device.impl.peermsg;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.store.Timestamp;
/**
* Device Advertisement message.
*/
public class DeviceAntiEntropyAdvertisement {
private final NodeId sender;
private final Map<DeviceFragmentId, Timestamp> deviceFingerPrints;
private final Map<PortFragmentId, Timestamp> portFingerPrints;
private final Map<DeviceId, Timestamp> offline;
public DeviceAntiEntropyAdvertisement(NodeId sender,
Map<DeviceFragmentId, Timestamp> devices,
Map<PortFragmentId, Timestamp> ports,
Map<DeviceId, Timestamp> offline) {
this.sender = checkNotNull(sender);
this.deviceFingerPrints = checkNotNull(devices);
this.portFingerPrints = checkNotNull(ports);
this.offline = checkNotNull(offline);
}
public NodeId sender() {
return sender;
}
public Map<DeviceFragmentId, Timestamp> deviceFingerPrints() {
return deviceFingerPrints;
}
public Map<PortFragmentId, Timestamp> ports() {
return portFingerPrints;
}
public Map<DeviceId, Timestamp> offline() {
return offline;
}
// For serializer
@SuppressWarnings("unused")
private DeviceAntiEntropyAdvertisement() {
this.sender = null;
this.deviceFingerPrints = null;
this.portFingerPrints = null;
this.offline = null;
}
}
package org.onlab.onos.store.device.impl.peermsg;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collection;
import org.onlab.onos.cluster.NodeId;
/**
* Message to request for other peers information.
*/
public class DeviceAntiEntropyRequest {
private final NodeId sender;
private final Collection<DeviceFragmentId> devices;
private final Collection<PortFragmentId> ports;
public DeviceAntiEntropyRequest(NodeId sender,
Collection<DeviceFragmentId> devices,
Collection<PortFragmentId> ports) {
this.sender = checkNotNull(sender);
this.devices = checkNotNull(devices);
this.ports = checkNotNull(ports);
}
public NodeId sender() {
return sender;
}
public Collection<DeviceFragmentId> devices() {
return devices;
}
public Collection<PortFragmentId> ports() {
return ports;
}
// For serializer
@SuppressWarnings("unused")
private DeviceAntiEntropyRequest() {
this.sender = null;
this.devices = null;
this.ports = null;
}
}
package org.onlab.onos.store.device.impl.peermsg;
import java.util.Objects;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.provider.ProviderId;
import com.google.common.base.MoreObjects;
/**
* Identifier for DeviceDesctiption from a Provider.
*/
public final class DeviceFragmentId {
public final ProviderId providerId;
public final DeviceId deviceId;
public DeviceFragmentId(DeviceId deviceId, ProviderId providerId) {
this.providerId = providerId;
this.deviceId = deviceId;
}
@Override
public int hashCode() {
return Objects.hash(providerId, deviceId);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof DeviceFragmentId)) {
return false;
}
DeviceFragmentId that = (DeviceFragmentId) obj;
return Objects.equals(this.deviceId, that.deviceId) &&
Objects.equals(this.providerId, that.providerId);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("providerId", providerId)
.add("deviceId", deviceId)
.toString();
}
// for serializer
@SuppressWarnings("unused")
private DeviceFragmentId() {
this.providerId = null;
this.deviceId = null;
}
}
\ No newline at end of file
package org.onlab.onos.store.device.impl.peermsg;
import java.util.Objects;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.provider.ProviderId;
import com.google.common.base.MoreObjects;
/**
* Identifier for PortDescription from a Provider.
*/
public final class PortFragmentId {
public final ProviderId providerId;
public final DeviceId deviceId;
public final PortNumber portNumber;
public PortFragmentId(DeviceId deviceId, ProviderId providerId,
PortNumber portNumber) {
this.providerId = providerId;
this.deviceId = deviceId;
this.portNumber = portNumber;
}
@Override
public int hashCode() {
return Objects.hash(providerId, deviceId, portNumber);
};
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof PortFragmentId)) {
return false;
}
PortFragmentId that = (PortFragmentId) obj;
return Objects.equals(this.deviceId, that.deviceId) &&
Objects.equals(this.portNumber, that.portNumber) &&
Objects.equals(this.providerId, that.providerId);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("providerId", providerId)
.add("deviceId", deviceId)
.add("portNumber", portNumber)
.toString();
}
// for serializer
@SuppressWarnings("unused")
private PortFragmentId() {
this.providerId = null;
this.deviceId = null;
this.portNumber = null;
}
}
\ No newline at end of file
/**
* Structure and utilities used for inter-Node messaging.
*/
package org.onlab.onos.store.device.impl.peermsg;
package org.onlab.onos.store.host.impl;
import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED;
import static org.onlab.onos.net.host.HostEvent.Type.HOST_MOVED;
import static org.onlab.onos.net.host.HostEvent.Type.HOST_REMOVED;
import static org.onlab.onos.net.host.HostEvent.Type.HOST_UPDATED;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.net.Annotations;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DefaultHost;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Host;
import org.onlab.onos.net.HostId;
import org.onlab.onos.net.HostLocation;
import org.onlab.onos.net.host.HostDescription;
import org.onlab.onos.net.host.HostEvent;
import org.onlab.onos.net.host.HostStore;
......@@ -33,10 +27,13 @@ import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.slf4j.Logger;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import static org.onlab.onos.net.host.HostEvent.Type.*;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Manages inventory of end-station hosts using trivial in-memory
......@@ -46,13 +43,13 @@ import com.google.common.collect.Sets;
@Component(immediate = true)
@Service
public class DistributedHostStore
extends AbstractStore<HostEvent, HostStoreDelegate>
implements HostStore {
extends AbstractStore<HostEvent, HostStoreDelegate>
implements HostStore {
private final Logger log = getLogger(getClass());
// Host inventory
private final Map<HostId, Host> hosts = new ConcurrentHashMap<>();
private final Map<HostId, StoredHost> hosts = new ConcurrentHashMap<>(2000000, 0.75f, 16);
// Hosts tracked by their location
private final Multimap<ConnectPoint, Host> locations = HashMultimap.create();
......@@ -72,8 +69,8 @@ implements HostStore {
@Override
public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
HostDescription hostDescription) {
Host host = hosts.get(hostId);
HostDescription hostDescription) {
StoredHost host = hosts.get(hostId);
if (host == null) {
return createHost(providerId, hostId, hostDescription);
}
......@@ -82,12 +79,12 @@ implements HostStore {
// creates a new host and sends HOST_ADDED
private HostEvent createHost(ProviderId providerId, HostId hostId,
HostDescription descr) {
DefaultHost newhost = new DefaultHost(providerId, hostId,
descr.hwAddress(),
descr.vlan(),
descr.location(),
descr.ipAddresses());
HostDescription descr) {
StoredHost newhost = new StoredHost(providerId, hostId,
descr.hwAddress(),
descr.vlan(),
descr.location(),
ImmutableSet.of(descr.ipAddress()));
synchronized (this) {
hosts.put(hostId, newhost);
locations.put(descr.location(), newhost);
......@@ -96,28 +93,24 @@ implements HostStore {
}
// checks for type of update to host, sends appropriate event
private HostEvent updateHost(ProviderId providerId, Host host,
HostDescription descr) {
DefaultHost updated;
private HostEvent updateHost(ProviderId providerId, StoredHost host,
HostDescription descr) {
HostEvent event;
if (!host.location().equals(descr.location())) {
updated = new DefaultHost(providerId, host.id(),
host.mac(),
host.vlan(),
descr.location(),
host.ipAddresses());
event = new HostEvent(HOST_MOVED, updated);
} else if (!(host.ipAddresses().equals(descr.ipAddresses()))) {
updated = new DefaultHost(providerId, host.id(),
host.mac(),
host.vlan(),
descr.location(),
descr.ipAddresses());
event = new HostEvent(HOST_UPDATED, updated);
} else {
host.setLocation(descr.location());
return new HostEvent(HOST_MOVED, host);
}
if (host.ipAddresses().contains(descr.ipAddress())) {
return null;
}
Set<IpPrefix> addresses = new HashSet<>(host.ipAddresses());
addresses.add(descr.ipAddress());
StoredHost updated = new StoredHost(providerId, host.id(),
host.mac(), host.vlan(),
descr.location(), addresses);
event = new HostEvent(HOST_UPDATED, updated);
synchronized (this) {
hosts.put(host.id(), updated);
locations.remove(host.location(), host);
......@@ -145,7 +138,7 @@ implements HostStore {
@Override
public Iterable<Host> getHosts() {
return Collections.unmodifiableSet(new HashSet<>(hosts.values()));
return ImmutableSet.<Host>copyOf(hosts.values());
}
@Override
......@@ -275,4 +268,35 @@ implements HostStore {
return addresses;
}
// Auxiliary extension to allow location to mutate.
private class StoredHost extends DefaultHost {
private HostLocation location;
/**
* Creates an end-station host using the supplied information.
*
* @param providerId provider identity
* @param id host identifier
* @param mac host MAC address
* @param vlan host VLAN identifier
* @param location host location
* @param ips host IP addresses
* @param annotations optional key/value annotations
*/
public StoredHost(ProviderId providerId, HostId id,
MacAddress mac, VlanId vlan, HostLocation location,
Set<IpPrefix> ips, Annotations... annotations) {
super(providerId, id, mac, vlan, location, ips, annotations);
this.location = location;
}
void setLocation(HostLocation location) {
this.location = location;
}
@Override
public HostLocation location() {
return location;
}
}
}
......
......@@ -31,7 +31,6 @@ import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.AbstractStore;
import org.onlab.onos.store.ClockService;
import org.onlab.onos.store.Timestamp;
import org.onlab.onos.store.VersionedValue;
import org.slf4j.Logger;
import com.google.common.collect.HashMultimap;
......
package org.onlab.onos.store;
package org.onlab.onos.store.link.impl;
import java.util.Objects;
import org.onlab.onos.store.Timestamp;
// TODO: remove once we stop using this
/**
* Wrapper class for a entity that is versioned
* and can either be up or down.
......
package org.onlab.onos.store.cluster.messaging.impl;
package org.onlab.onos.store.serializers;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.store.cluster.messaging.ClusterMessage;
......@@ -35,4 +35,4 @@ public final class ClusterMessageSerializer extends Serializer<ClusterMessage> {
byte[] payload = input.readBytes(payloadSize);
return new ClusterMessage(sender, subject, payload);
}
}
\ No newline at end of file
}
......
package org.onlab.onos.store.serializers;
import org.onlab.onos.store.common.impl.MastershipBasedTimestamp;
import org.onlab.onos.store.common.impl.Timestamped;
import org.onlab.util.KryoPool;
public final class DistributedStoreSerializers {
/**
* KryoPool which can serialize ON.lab misc classes.
*/
public static final KryoPool COMMON = KryoPool.newBuilder()
.register(KryoPoolUtil.API)
.register(Timestamped.class)
.register(MastershipBasedTimestamp.class, new MastershipBasedTimestampSerializer())
.build();
// avoid instantiation
private DistributedStoreSerializers() {}
}
package org.onlab.onos.store.common.impl;
package org.onlab.onos.store.serializers;
import org.onlab.onos.store.common.impl.MastershipBasedTimestamp;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
......@@ -7,12 +9,12 @@ import com.esotericsoftware.kryo.io.Output;
// To be used if Timestamp ever needs to cross bundle boundary.
/**
* Kryo Serializer for {@link DeviceMastershipBasedTimestamp}.
* Kryo Serializer for {@link MastershipBasedTimestamp}.
*/
public class MastershipBasedTimestampSerializer extends Serializer<DeviceMastershipBasedTimestamp> {
public class MastershipBasedTimestampSerializer extends Serializer<MastershipBasedTimestamp> {
/**
* Creates a serializer for {@link DeviceMastershipBasedTimestamp}.
* Creates a serializer for {@link MastershipBasedTimestamp}.
*/
public MastershipBasedTimestampSerializer() {
// non-null, immutable
......@@ -20,15 +22,15 @@ public class MastershipBasedTimestampSerializer extends Serializer<DeviceMasters
}
@Override
public void write(Kryo kryo, Output output, DeviceMastershipBasedTimestamp object) {
public void write(Kryo kryo, Output output, MastershipBasedTimestamp object) {
output.writeInt(object.termNumber());
output.writeInt(object.sequenceNumber());
}
@Override
public DeviceMastershipBasedTimestamp read(Kryo kryo, Input input, Class<DeviceMastershipBasedTimestamp> type) {
public MastershipBasedTimestamp read(Kryo kryo, Input input, Class<MastershipBasedTimestamp> type) {
final int term = input.readInt();
final int sequence = input.readInt();
return new DeviceMastershipBasedTimestamp(term, sequence);
return new MastershipBasedTimestamp(term, sequence);
}
}
......
package org.onlab.onos.store.cluster.messaging.impl;
package org.onlab.onos.store.serializers;
import org.onlab.onos.store.cluster.messaging.MessageSubject;
......
......@@ -6,25 +6,26 @@ import java.nio.ByteBuffer;
import org.junit.Test;
import org.onlab.onos.store.Timestamp;
import org.onlab.onos.store.serializers.MastershipBasedTimestampSerializer;
import org.onlab.util.KryoPool;
import com.google.common.testing.EqualsTester;
/**
* Test of {@link DeviceMastershipBasedTimestamp}.
* Test of {@link MastershipBasedTimestamp}.
*/
public class MastershipBasedTimestampTest {
private static final Timestamp TS_1_1 = new DeviceMastershipBasedTimestamp(1, 1);
private static final Timestamp TS_1_2 = new DeviceMastershipBasedTimestamp(1, 2);
private static final Timestamp TS_2_1 = new DeviceMastershipBasedTimestamp(2, 1);
private static final Timestamp TS_2_2 = new DeviceMastershipBasedTimestamp(2, 2);
private static final Timestamp TS_1_1 = new MastershipBasedTimestamp(1, 1);
private static final Timestamp TS_1_2 = new MastershipBasedTimestamp(1, 2);
private static final Timestamp TS_2_1 = new MastershipBasedTimestamp(2, 1);
private static final Timestamp TS_2_2 = new MastershipBasedTimestamp(2, 2);
@Test
public final void testBasic() {
final int termNumber = 5;
final int sequenceNumber = 6;
DeviceMastershipBasedTimestamp ts = new DeviceMastershipBasedTimestamp(termNumber,
MastershipBasedTimestamp ts = new MastershipBasedTimestamp(termNumber,
sequenceNumber);
assertEquals(termNumber, ts.termNumber());
......@@ -34,7 +35,7 @@ public class MastershipBasedTimestampTest {
@Test
public final void testCompareTo() {
assertTrue(TS_1_1.compareTo(TS_1_1) == 0);
assertTrue(TS_1_1.compareTo(new DeviceMastershipBasedTimestamp(1, 1)) == 0);
assertTrue(TS_1_1.compareTo(new MastershipBasedTimestamp(1, 1)) == 0);
assertTrue(TS_1_1.compareTo(TS_1_2) < 0);
assertTrue(TS_1_2.compareTo(TS_1_1) > 0);
......@@ -48,14 +49,14 @@ public class MastershipBasedTimestampTest {
@Test
public final void testEqualsObject() {
new EqualsTester()
.addEqualityGroup(new DeviceMastershipBasedTimestamp(1, 1),
new DeviceMastershipBasedTimestamp(1, 1), TS_1_1)
.addEqualityGroup(new DeviceMastershipBasedTimestamp(1, 2),
new DeviceMastershipBasedTimestamp(1, 2), TS_1_2)
.addEqualityGroup(new DeviceMastershipBasedTimestamp(2, 1),
new DeviceMastershipBasedTimestamp(2, 1), TS_2_1)
.addEqualityGroup(new DeviceMastershipBasedTimestamp(2, 2),
new DeviceMastershipBasedTimestamp(2, 2), TS_2_2)
.addEqualityGroup(new MastershipBasedTimestamp(1, 1),
new MastershipBasedTimestamp(1, 1), TS_1_1)
.addEqualityGroup(new MastershipBasedTimestamp(1, 2),
new MastershipBasedTimestamp(1, 2), TS_1_2)
.addEqualityGroup(new MastershipBasedTimestamp(2, 1),
new MastershipBasedTimestamp(2, 1), TS_2_1)
.addEqualityGroup(new MastershipBasedTimestamp(2, 2),
new MastershipBasedTimestamp(2, 2), TS_2_2)
.testEquals();
}
......@@ -63,7 +64,7 @@ public class MastershipBasedTimestampTest {
public final void testKryoSerializable() {
final ByteBuffer buffer = ByteBuffer.allocate(1 * 1024 * 1024);
final KryoPool kryos = KryoPool.newBuilder()
.register(DeviceMastershipBasedTimestamp.class)
.register(MastershipBasedTimestamp.class)
.build();
kryos.serialize(TS_2_1, buffer);
......@@ -79,7 +80,7 @@ public class MastershipBasedTimestampTest {
public final void testKryoSerializableWithHandcraftedSerializer() {
final ByteBuffer buffer = ByteBuffer.allocate(1 * 1024 * 1024);
final KryoPool kryos = KryoPool.newBuilder()
.register(DeviceMastershipBasedTimestamp.class, new MastershipBasedTimestampSerializer())
.register(MastershipBasedTimestamp.class, new MastershipBasedTimestampSerializer())
.build();
kryos.serialize(TS_1_2, buffer);
......
......@@ -6,7 +6,6 @@ import java.nio.ByteBuffer;
import org.junit.Test;
import org.onlab.onos.store.Timestamp;
import org.onlab.onos.store.Timestamped;
import org.onlab.util.KryoPool;
import com.google.common.testing.EqualsTester;
......@@ -16,9 +15,9 @@ import com.google.common.testing.EqualsTester;
*/
public class TimestampedTest {
private static final Timestamp TS_1_1 = new DeviceMastershipBasedTimestamp(1, 1);
private static final Timestamp TS_1_2 = new DeviceMastershipBasedTimestamp(1, 2);
private static final Timestamp TS_2_1 = new DeviceMastershipBasedTimestamp(2, 1);
private static final Timestamp TS_1_1 = new MastershipBasedTimestamp(1, 1);
private static final Timestamp TS_1_2 = new MastershipBasedTimestamp(1, 2);
private static final Timestamp TS_2_1 = new MastershipBasedTimestamp(2, 1);
@Test
public final void testHashCode() {
......@@ -80,7 +79,7 @@ public class TimestampedTest {
final ByteBuffer buffer = ByteBuffer.allocate(1 * 1024 * 1024);
final KryoPool kryos = KryoPool.newBuilder()
.register(Timestamped.class,
DeviceMastershipBasedTimestamp.class)
MastershipBasedTimestamp.class)
.build();
Timestamped<String> original = new Timestamped<>("foobar", TS_1_1);
......
......@@ -25,6 +25,7 @@ import org.onlab.onos.cluster.ClusterService;
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.ControllerNode.State;
import org.onlab.onos.cluster.DefaultControllerNode;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.Annotations;
import org.onlab.onos.net.DefaultAnnotations;
......@@ -39,7 +40,6 @@ import org.onlab.onos.net.device.DeviceDescription;
import org.onlab.onos.net.device.DeviceEvent;
import org.onlab.onos.net.device.DeviceStore;
import org.onlab.onos.net.device.DeviceStoreDelegate;
import org.onlab.onos.net.device.DeviceMastershipTerm;
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.ClockService;
......@@ -113,8 +113,8 @@ public class GossipDeviceStoreTest {
deviceClockManager.activate();
clockService = deviceClockManager;
deviceClockManager.setMastershipTerm(DID1, DeviceMastershipTerm.of(MYSELF, 1));
deviceClockManager.setMastershipTerm(DID2, DeviceMastershipTerm.of(MYSELF, 2));
deviceClockManager.setMastershipTerm(DID1, MastershipTerm.of(MYSELF, 1));
deviceClockManager.setMastershipTerm(DID2, MastershipTerm.of(MYSELF, 2));
ClusterCommunicationService clusterCommunicator = new TestClusterCommunicationService();
ClusterService clusterService = new TestClusterService();
......
......@@ -46,10 +46,6 @@
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>
</dependency>
<dependency>
<groupId>de.javakaffee</groupId>
<artifactId>kryo-serializers</artifactId>
</dependency>
</dependencies>
<build>
......
package org.onlab.onos.store.cluster.impl;
import static org.onlab.onos.net.device.DeviceMastershipEvent.Type.MASTER_CHANGED;
import static org.onlab.onos.cluster.MastershipEvent.Type.MASTER_CHANGED;
import java.util.Map;
import java.util.Set;
......@@ -12,13 +12,13 @@ import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.cluster.ClusterService;
import org.onlab.onos.cluster.MastershipEvent;
import org.onlab.onos.cluster.MastershipStore;
import org.onlab.onos.cluster.MastershipStoreDelegate;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
import org.onlab.onos.net.device.DeviceMastershipEvent;
import org.onlab.onos.net.device.DeviceMastershipStore;
import org.onlab.onos.net.device.DeviceMastershipStoreDelegate;
import org.onlab.onos.net.device.DeviceMastershipTerm;
import org.onlab.onos.store.common.AbstractHazelcastStore;
import com.google.common.collect.ImmutableSet;
......@@ -32,9 +32,9 @@ import com.hazelcast.core.MultiMap;
*/
@Component(immediate = true)
@Service
public class DistributedDeviceMastershipStore
extends AbstractHazelcastStore<DeviceMastershipEvent, DeviceMastershipStoreDelegate>
implements DeviceMastershipStore {
public class DistributedMastershipStore
extends AbstractHazelcastStore<MastershipEvent, MastershipStoreDelegate>
implements MastershipStore {
//arbitrary lock name
private static final String LOCK = "lock";
......@@ -100,7 +100,7 @@ implements DeviceMastershipStore {
}
@Override
public DeviceMastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) {
public MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) {
byte [] did = serialize(deviceId);
byte [] nid = serialize(nodeId);
......@@ -123,12 +123,12 @@ implements DeviceMastershipStore {
masters.put(did, nid);
evict(nid, did);
updateTerm(did);
return new DeviceMastershipEvent(MASTER_CHANGED, deviceId, nodeId);
return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
case NONE:
masters.put(did, nid);
evict(nid, did);
updateTerm(did);
return new DeviceMastershipEvent(MASTER_CHANGED, deviceId, nodeId);
return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
default:
log.warn("unknown Mastership Role {}", role);
return null;
......@@ -191,21 +191,21 @@ implements DeviceMastershipStore {
}
@Override
public DeviceMastershipTerm getTermFor(DeviceId deviceId) {
public MastershipTerm getTermFor(DeviceId deviceId) {
byte[] did = serialize(deviceId);
if ((masters.get(did) == null) ||
(terms.get(did) == null)) {
return null;
}
return DeviceMastershipTerm.of(
return MastershipTerm.of(
(NodeId) deserialize(masters.get(did)), terms.get(did));
}
@Override
public DeviceMastershipEvent setStandby(NodeId nodeId, DeviceId deviceId) {
public MastershipEvent setStandby(NodeId nodeId, DeviceId deviceId) {
byte [] did = serialize(deviceId);
byte [] nid = serialize(nodeId);
DeviceMastershipEvent event = null;
MastershipEvent event = null;
ILock lock = theInstance.getLock(LOCK);
lock.lock();
......@@ -231,10 +231,10 @@ implements DeviceMastershipStore {
}
@Override
public DeviceMastershipEvent relinquishRole(NodeId nodeId, DeviceId deviceId) {
public MastershipEvent relinquishRole(NodeId nodeId, DeviceId deviceId) {
byte [] did = serialize(deviceId);
byte [] nid = serialize(nodeId);
DeviceMastershipEvent event = null;
MastershipEvent event = null;
ILock lock = theInstance.getLock(LOCK);
lock.lock();
......@@ -260,7 +260,7 @@ implements DeviceMastershipStore {
}
//helper to fetch a new master candidate for a given device.
private DeviceMastershipEvent reelect(NodeId current, DeviceId deviceId) {
private MastershipEvent reelect(NodeId current, DeviceId deviceId) {
byte [] did = serialize(deviceId);
byte [] nid = serialize(current);
......@@ -281,7 +281,7 @@ implements DeviceMastershipStore {
evict(backup, did);
Integer term = terms.get(did);
terms.put(did, ++term);
return new DeviceMastershipEvent(
return new MastershipEvent(
MASTER_CHANGED, deviceId, (NodeId) deserialize(backup));
}
}
......@@ -320,7 +320,7 @@ implements DeviceMastershipStore {
@Override
protected void onAdd(DeviceId deviceId, NodeId nodeId) {
notifyDelegate(new DeviceMastershipEvent(MASTER_CHANGED, deviceId, nodeId));
notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, nodeId));
}
@Override
......
......@@ -21,12 +21,12 @@ import org.onlab.onos.cluster.ClusterService;
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.ControllerNode.State;
import org.onlab.onos.cluster.DefaultControllerNode;
import org.onlab.onos.cluster.MastershipEvent;
import org.onlab.onos.cluster.MastershipEvent.Type;
import org.onlab.onos.cluster.MastershipStoreDelegate;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.DeviceMastershipEvent;
import org.onlab.onos.net.device.DeviceMastershipStoreDelegate;
import org.onlab.onos.net.device.DeviceMastershipTerm;
import org.onlab.onos.net.device.DeviceMastershipEvent.Type;
import org.onlab.onos.store.common.StoreManager;
import org.onlab.onos.store.common.StoreService;
import org.onlab.onos.store.common.TestStoreManager;
......@@ -40,7 +40,7 @@ import com.hazelcast.core.Hazelcast;
/**
* Test of the Hazelcast-based distributed MastershipStore implementation.
*/
public class DistributedDeviceMastershipStoreTest {
public class DistributedMastershipStoreTest {
private static final DeviceId DID1 = DeviceId.deviceId("of:01");
private static final DeviceId DID2 = DeviceId.deviceId("of:02");
......@@ -54,8 +54,8 @@ public class DistributedDeviceMastershipStoreTest {
private static final ControllerNode CN1 = new DefaultControllerNode(N1, IP);
private static final ControllerNode CN2 = new DefaultControllerNode(N2, IP);
private DistributedDeviceMastershipStore dms;
private TestDistributedDeviceMastershipStore testStore;
private DistributedMastershipStore dms;
private TestDistributedMastershipStore testStore;
private KryoSerializer serializationMgr;
private StoreManager storeMgr;
......@@ -77,11 +77,11 @@ public class DistributedDeviceMastershipStoreTest {
serializationMgr = new KryoSerializer();
dms = new TestDistributedDeviceMastershipStore(storeMgr, serializationMgr);
dms = new TestDistributedMastershipStore(storeMgr, serializationMgr);
dms.clusterService = new TestClusterService();
dms.activate();
testStore = (TestDistributedDeviceMastershipStore) dms;
testStore = (TestDistributedMastershipStore) dms;
}
@After
......@@ -133,7 +133,7 @@ public class DistributedDeviceMastershipStoreTest {
assertEquals("wrong role for NONE:", MASTER, dms.requestRole(DID1));
assertTrue("wrong state for store:", !dms.terms.isEmpty());
assertEquals("wrong term",
DeviceMastershipTerm.of(N1, 0), dms.getTermFor(DID1));
MastershipTerm.of(N1, 0), dms.getTermFor(DID1));
//CN2 now local. DID2 has N1 as MASTER so N2 is STANDBY
testStore.setCurrent(CN2);
......@@ -143,7 +143,7 @@ public class DistributedDeviceMastershipStoreTest {
//change term and requestRole() again; should persist
testStore.increment(DID2);
assertEquals("wrong role for STANDBY:", STANDBY, dms.requestRole(DID2));
assertEquals("wrong term", DeviceMastershipTerm.of(N1, 1), dms.getTermFor(DID2));
assertEquals("wrong term", MastershipTerm.of(N1, 1), dms.getTermFor(DID2));
}
@Test
......@@ -155,15 +155,15 @@ public class DistributedDeviceMastershipStoreTest {
//switch over to N2
assertEquals("wrong event:", Type.MASTER_CHANGED, dms.setMaster(N2, DID1).type());
assertEquals("wrong term", DeviceMastershipTerm.of(N2, 1), dms.getTermFor(DID1));
assertEquals("wrong term", MastershipTerm.of(N2, 1), dms.getTermFor(DID1));
//orphan switch - should be rare case
assertEquals("wrong event:", Type.MASTER_CHANGED, dms.setMaster(N2, DID2).type());
assertEquals("wrong term", DeviceMastershipTerm.of(N2, 0), dms.getTermFor(DID2));
assertEquals("wrong term", MastershipTerm.of(N2, 0), dms.getTermFor(DID2));
//disconnect and reconnect - sign of failing re-election or single-instance channel
testStore.reset(true, false, false);
dms.setMaster(N2, DID2);
assertEquals("wrong term", DeviceMastershipTerm.of(N2, 1), dms.getTermFor(DID2));
assertEquals("wrong term", MastershipTerm.of(N2, 1), dms.getTermFor(DID2));
}
@Test
......@@ -211,9 +211,9 @@ public class DistributedDeviceMastershipStoreTest {
//shamelessly copy other distributed store tests
final CountDownLatch addLatch = new CountDownLatch(1);
DeviceMastershipStoreDelegate checkAdd = new DeviceMastershipStoreDelegate() {
MastershipStoreDelegate checkAdd = new MastershipStoreDelegate() {
@Override
public void notify(DeviceMastershipEvent event) {
public void notify(MastershipEvent event) {
assertEquals("wrong event:", Type.MASTER_CHANGED, event.type());
assertEquals("wrong subject", DID1, event.subject());
assertEquals("wrong subject", N1, event.master());
......@@ -227,9 +227,9 @@ public class DistributedDeviceMastershipStoreTest {
assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS));
}
private class TestDistributedDeviceMastershipStore extends
DistributedDeviceMastershipStore {
public TestDistributedDeviceMastershipStore(StoreService storeService,
private class TestDistributedMastershipStore extends
DistributedMastershipStore {
public TestDistributedMastershipStore(StoreService storeService,
KryoSerializer kryoSerialization) {
this.storeService = storeService;
this.serializer = kryoSerialization;
......
......@@ -35,8 +35,8 @@
<artifactId>hazelcast</artifactId>
</dependency>
<dependency>
<groupId>de.javakaffee</groupId>
<artifactId>kryo-serializers</artifactId>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
......
......@@ -23,11 +23,6 @@
</dependency>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-core-serializers</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-core-hz-common</artifactId>
<version>${project.version}</version>
</dependency>
......@@ -46,10 +41,6 @@
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>
</dependency>
<dependency>
<groupId>de.javakaffee</groupId>
<artifactId>kryo-serializers</artifactId>
</dependency>
</dependencies>
<build>
......
......@@ -2,8 +2,8 @@ package org.onlab.onos.store.device.impl;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.DeviceMastershipTerm;
import org.onlab.onos.store.ClockProviderService;
// FIXME: Code clone in onos-core-trivial, onos-core-hz-net
......@@ -15,6 +15,6 @@ import org.onlab.onos.store.ClockProviderService;
public class NoOpClockProviderService implements ClockProviderService {
@Override
public void setMastershipTerm(DeviceId deviceId, DeviceMastershipTerm term) {
public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
}
}
......
package org.onlab.onos.store.host.impl;
import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED;
import static org.onlab.onos.net.host.HostEvent.Type.HOST_MOVED;
import static org.onlab.onos.net.host.HostEvent.Type.HOST_REMOVED;
import static org.onlab.onos.net.host.HostEvent.Type.HOST_UPDATED;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.net.Annotations;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DefaultHost;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Host;
import org.onlab.onos.net.HostId;
import org.onlab.onos.net.HostLocation;
import org.onlab.onos.net.host.HostDescription;
import org.onlab.onos.net.host.HostEvent;
import org.onlab.onos.net.host.HostStore;
......@@ -33,10 +27,13 @@ import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.slf4j.Logger;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import static org.onlab.onos.net.host.HostEvent.Type.*;
import static org.slf4j.LoggerFactory.getLogger;
/**
* TEMPORARY: Manages inventory of end-station hosts using distributed
......@@ -46,13 +43,13 @@ import com.google.common.collect.Sets;
@Component(immediate = true)
@Service
public class DistributedHostStore
extends AbstractStore<HostEvent, HostStoreDelegate>
implements HostStore {
extends AbstractStore<HostEvent, HostStoreDelegate>
implements HostStore {
private final Logger log = getLogger(getClass());
// Host inventory
private final Map<HostId, Host> hosts = new ConcurrentHashMap<>();
private final Map<HostId, StoredHost> hosts = new ConcurrentHashMap<>(2000000, 0.75f, 16);
// Hosts tracked by their location
private final Multimap<ConnectPoint, Host> locations = HashMultimap.create();
......@@ -72,8 +69,8 @@ implements HostStore {
@Override
public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
HostDescription hostDescription) {
Host host = hosts.get(hostId);
HostDescription hostDescription) {
StoredHost host = hosts.get(hostId);
if (host == null) {
return createHost(providerId, hostId, hostDescription);
}
......@@ -82,12 +79,12 @@ implements HostStore {
// creates a new host and sends HOST_ADDED
private HostEvent createHost(ProviderId providerId, HostId hostId,
HostDescription descr) {
DefaultHost newhost = new DefaultHost(providerId, hostId,
descr.hwAddress(),
descr.vlan(),
descr.location(),
descr.ipAddresses());
HostDescription descr) {
StoredHost newhost = new StoredHost(providerId, hostId,
descr.hwAddress(),
descr.vlan(),
descr.location(),
ImmutableSet.of(descr.ipAddress()));
synchronized (this) {
hosts.put(hostId, newhost);
locations.put(descr.location(), newhost);
......@@ -96,28 +93,24 @@ implements HostStore {
}
// checks for type of update to host, sends appropriate event
private HostEvent updateHost(ProviderId providerId, Host host,
HostDescription descr) {
DefaultHost updated;
private HostEvent updateHost(ProviderId providerId, StoredHost host,
HostDescription descr) {
HostEvent event;
if (!host.location().equals(descr.location())) {
updated = new DefaultHost(providerId, host.id(),
host.mac(),
host.vlan(),
descr.location(),
host.ipAddresses());
event = new HostEvent(HOST_MOVED, updated);
} else if (!(host.ipAddresses().equals(descr.ipAddresses()))) {
updated = new DefaultHost(providerId, host.id(),
host.mac(),
host.vlan(),
descr.location(),
descr.ipAddresses());
event = new HostEvent(HOST_UPDATED, updated);
} else {
host.setLocation(descr.location());
return new HostEvent(HOST_MOVED, host);
}
if (host.ipAddresses().contains(descr.ipAddress())) {
return null;
}
Set<IpPrefix> addresses = new HashSet<>(host.ipAddresses());
addresses.add(descr.ipAddress());
StoredHost updated = new StoredHost(providerId, host.id(),
host.mac(), host.vlan(),
descr.location(), addresses);
event = new HostEvent(HOST_UPDATED, updated);
synchronized (this) {
hosts.put(host.id(), updated);
locations.remove(host.location(), host);
......@@ -145,7 +138,7 @@ implements HostStore {
@Override
public Iterable<Host> getHosts() {
return Collections.unmodifiableSet(new HashSet<>(hosts.values()));
return ImmutableSet.<Host>copyOf(hosts.values());
}
@Override
......@@ -275,4 +268,35 @@ implements HostStore {
return addresses;
}
// Auxiliary extension to allow location to mutate.
private class StoredHost extends DefaultHost {
private HostLocation location;
/**
* Creates an end-station host using the supplied information.
*
* @param providerId provider identity
* @param id host identifier
* @param mac host MAC address
* @param vlan host VLAN identifier
* @param location host location
* @param ips host IP addresses
* @param annotations optional key/value annotations
*/
public StoredHost(ProviderId providerId, HostId id,
MacAddress mac, VlanId vlan, HostLocation location,
Set<IpPrefix> ips, Annotations... annotations) {
super(providerId, id, mac, vlan, location, ips, annotations);
this.location = location;
}
void setLocation(HostLocation location) {
this.location = location;
}
@Override
public HostLocation location() {
return location;
}
}
}
......
......@@ -26,8 +26,13 @@
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
<dependency>
<groupId>de.javakaffee</groupId>
<artifactId>kryo-serializers</artifactId>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-testlib</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
......
......@@ -7,6 +7,7 @@ import java.util.HashMap;
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.DefaultControllerNode;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DefaultAnnotations;
......@@ -23,14 +24,12 @@ import org.onlab.onos.net.Port;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.device.DefaultDeviceDescription;
import org.onlab.onos.net.device.DefaultPortDescription;
import org.onlab.onos.net.device.DeviceMastershipTerm;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.Timestamp;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.util.KryoPool;
import de.javakaffee.kryoserializers.URISerializer;
public final class KryoPoolUtil {
/**
......@@ -63,7 +62,9 @@ public final class KryoPoolUtil {
Port.class,
DefaultPortDescription.class,
Element.class,
Link.Type.class
Link.Type.class,
Timestamp.class
)
.register(URI.class, new URISerializer())
.register(NodeId.class, new NodeIdSerializer())
......@@ -74,7 +75,7 @@ public final class KryoPoolUtil {
.register(LinkKey.class, new LinkKeySerializer())
.register(ConnectPoint.class, new ConnectPointSerializer())
.register(DefaultLink.class, new DefaultLinkSerializer())
.register(DeviceMastershipTerm.class, new MastershipTermSerializer())
.register(MastershipTerm.class, new MastershipTermSerializer())
.register(MastershipRole.class, new MastershipRoleSerializer())
.build();
......
package org.onlab.onos.store.serializers;
import org.onlab.util.KryoPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
/**
......@@ -11,10 +8,8 @@ import java.nio.ByteBuffer;
*/
public class KryoSerializer implements StoreSerializer {
private final Logger log = LoggerFactory.getLogger(getClass());
protected KryoPool serializerPool;
public KryoSerializer() {
setupKryoPool();
}
......
package org.onlab.onos.store.serializers;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.device.DeviceMastershipTerm;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
/**
* Kryo Serializer for {@link org.onlab.onos.net.device.DeviceMastershipTerm}.
* Kryo Serializer for {@link org.onlab.onos.cluster.MastershipTerm}.
*/
public class MastershipTermSerializer extends Serializer<DeviceMastershipTerm> {
public class MastershipTermSerializer extends Serializer<MastershipTerm> {
/**
* Creates {@link DeviceMastershipTerm} serializer instance.
* Creates {@link MastershipTerm} serializer instance.
*/
public MastershipTermSerializer() {
// non-null, immutable
......@@ -22,14 +21,14 @@ public class MastershipTermSerializer extends Serializer<DeviceMastershipTerm> {
}
@Override
public DeviceMastershipTerm read(Kryo kryo, Input input, Class<DeviceMastershipTerm> type) {
public MastershipTerm read(Kryo kryo, Input input, Class<MastershipTerm> type) {
final NodeId node = new NodeId(input.readString());
final int term = input.readInt();
return DeviceMastershipTerm.of(node, term);
return MastershipTerm.of(node, term);
}
@Override
public void write(Kryo kryo, Output output, DeviceMastershipTerm object) {
public void write(Kryo kryo, Output output, MastershipTerm object) {
output.writeString(object.master().toString());
output.writeInt(object.termNumber());
}
......
package org.onlab.onos.store.serializers;
import java.net.URI;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
/**
* Serializer for {@link URI}.
*/
public class URISerializer extends Serializer<URI> {
/**
* Creates {@link URI} serializer instance.
*/
public URISerializer() {
super(false);
}
@Override
public void write(Kryo kryo, Output output, URI object) {
output.writeString(object.toString());
}
@Override
public URI read(Kryo kryo, Input input, Class<URI> type) {
return URI.create(input.readString());
}
}
......@@ -10,6 +10,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.Annotations;
import org.onlab.onos.net.ConnectPoint;
......@@ -24,7 +25,6 @@ import org.onlab.onos.net.LinkKey;
import org.onlab.onos.net.MastershipRole;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.SparseAnnotations;
import org.onlab.onos.net.device.DeviceMastershipTerm;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
......@@ -114,7 +114,7 @@ public class KryoSerializerTest {
testSerialized(PID);
testSerialized(PIDA);
testSerialized(new NodeId("bar"));
testSerialized(DeviceMastershipTerm.of(new NodeId("foo"), 2));
testSerialized(MastershipTerm.of(new NodeId("foo"), 2));
for (MastershipRole role : MastershipRole.values()) {
testSerialized(role);
}
......
......@@ -2,8 +2,8 @@ package org.onlab.onos.store.trivial.impl;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.DeviceMastershipTerm;
import org.onlab.onos.store.ClockProviderService;
//FIXME: Code clone in onos-core-trivial, onos-core-hz-net
......@@ -15,6 +15,6 @@ import org.onlab.onos.store.ClockProviderService;
public class NoOpClockProviderService implements ClockProviderService {
@Override
public void setMastershipTerm(DeviceId deviceId, DeviceMastershipTerm term) {
public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
}
}
......
package org.onlab.onos.store.trivial.impl;
import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED;
import static org.onlab.onos.net.host.HostEvent.Type.HOST_MOVED;
import static org.onlab.onos.net.host.HostEvent.Type.HOST_REMOVED;
import static org.onlab.onos.net.host.HostEvent.Type.HOST_UPDATED;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.net.Annotations;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DefaultHost;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Host;
import org.onlab.onos.net.HostId;
import org.onlab.onos.net.HostLocation;
import org.onlab.onos.net.host.HostDescription;
import org.onlab.onos.net.host.HostEvent;
import org.onlab.onos.net.host.HostStore;
......@@ -33,10 +27,13 @@ import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.slf4j.Logger;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import static org.onlab.onos.net.host.HostEvent.Type.*;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Manages inventory of end-station hosts using trivial in-memory
......@@ -51,7 +48,7 @@ public class SimpleHostStore
private final Logger log = getLogger(getClass());
// Host inventory
private final Map<HostId, Host> hosts = new ConcurrentHashMap<>();
private final Map<HostId, StoredHost> hosts = new ConcurrentHashMap<>(2000000, 0.75f, 16);
// Hosts tracked by their location
private final Multimap<ConnectPoint, Host> locations = HashMultimap.create();
......@@ -72,7 +69,7 @@ public class SimpleHostStore
@Override
public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
HostDescription hostDescription) {
Host host = hosts.get(hostId);
StoredHost host = hosts.get(hostId);
if (host == null) {
return createHost(providerId, hostId, hostDescription);
}
......@@ -82,11 +79,11 @@ public class SimpleHostStore
// creates a new host and sends HOST_ADDED
private HostEvent createHost(ProviderId providerId, HostId hostId,
HostDescription descr) {
DefaultHost newhost = new DefaultHost(providerId, hostId,
descr.hwAddress(),
descr.vlan(),
descr.location(),
descr.ipAddresses());
StoredHost newhost = new StoredHost(providerId, hostId,
descr.hwAddress(),
descr.vlan(),
descr.location(),
ImmutableSet.of(descr.ipAddress()));
synchronized (this) {
hosts.put(hostId, newhost);
locations.put(descr.location(), newhost);
......@@ -95,28 +92,24 @@ public class SimpleHostStore
}
// checks for type of update to host, sends appropriate event
private HostEvent updateHost(ProviderId providerId, Host host,
private HostEvent updateHost(ProviderId providerId, StoredHost host,
HostDescription descr) {
DefaultHost updated;
HostEvent event;
if (!host.location().equals(descr.location())) {
updated = new DefaultHost(providerId, host.id(),
host.mac(),
host.vlan(),
descr.location(),
host.ipAddresses());
event = new HostEvent(HOST_MOVED, updated);
} else if (!(host.ipAddresses().equals(descr.ipAddresses()))) {
updated = new DefaultHost(providerId, host.id(),
host.mac(),
host.vlan(),
descr.location(),
descr.ipAddresses());
event = new HostEvent(HOST_UPDATED, updated);
} else {
host.setLocation(descr.location());
return new HostEvent(HOST_MOVED, host);
}
if (host.ipAddresses().contains(descr.ipAddress())) {
return null;
}
Set<IpPrefix> addresses = new HashSet<>(host.ipAddresses());
addresses.add(descr.ipAddress());
StoredHost updated = new StoredHost(providerId, host.id(),
host.mac(), host.vlan(),
descr.location(), addresses);
event = new HostEvent(HOST_UPDATED, updated);
synchronized (this) {
hosts.put(host.id(), updated);
locations.remove(host.location(), host);
......@@ -144,7 +137,7 @@ public class SimpleHostStore
@Override
public Iterable<Host> getHosts() {
return Collections.unmodifiableSet(new HashSet<>(hosts.values()));
return ImmutableSet.<Host>copyOf(hosts.values());
}
@Override
......@@ -274,4 +267,35 @@ public class SimpleHostStore
return addresses;
}
// Auxiliary extension to allow location to mutate.
private class StoredHost extends DefaultHost {
private HostLocation location;
/**
* Creates an end-station host using the supplied information.
*
* @param providerId provider identity
* @param id host identifier
* @param mac host MAC address
* @param vlan host VLAN identifier
* @param location host location
* @param ips host IP addresses
* @param annotations optional key/value annotations
*/
public StoredHost(ProviderId providerId, HostId id,
MacAddress mac, VlanId vlan, HostLocation location,
Set<IpPrefix> ips, Annotations... annotations) {
super(providerId, id, mac, vlan, location, ips, annotations);
this.location = location;
}
void setLocation(HostLocation location) {
this.location = location;
}
@Override
public HostLocation location() {
return location;
}
}
}
......
......@@ -15,18 +15,18 @@ import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.DefaultControllerNode;
import org.onlab.onos.cluster.MastershipEvent;
import org.onlab.onos.cluster.MastershipStore;
import org.onlab.onos.cluster.MastershipStoreDelegate;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
import org.onlab.onos.net.device.DeviceMastershipEvent;
import org.onlab.onos.net.device.DeviceMastershipStore;
import org.onlab.onos.net.device.DeviceMastershipStoreDelegate;
import org.onlab.onos.net.device.DeviceMastershipTerm;
import org.onlab.onos.store.AbstractStore;
import org.onlab.packet.IpPrefix;
import org.slf4j.Logger;
import static org.onlab.onos.net.device.DeviceMastershipEvent.Type.*;
import static org.onlab.onos.cluster.MastershipEvent.Type.*;
/**
* Manages inventory of controller mastership over devices using
......@@ -35,8 +35,8 @@ import static org.onlab.onos.net.device.DeviceMastershipEvent.Type.*;
@Component(immediate = true)
@Service
public class SimpleMastershipStore
extends AbstractStore<DeviceMastershipEvent, DeviceMastershipStoreDelegate>
implements DeviceMastershipStore {
extends AbstractStore<MastershipEvent, MastershipStoreDelegate>
implements MastershipStore {
private final Logger log = getLogger(getClass());
......@@ -63,7 +63,7 @@ public class SimpleMastershipStore
}
@Override
public DeviceMastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) {
public MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) {
MastershipRole role = getRole(nodeId, deviceId);
synchronized (this) {
......@@ -86,7 +86,7 @@ public class SimpleMastershipStore
}
}
return new DeviceMastershipEvent(MASTER_CHANGED, deviceId, nodeId);
return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
}
@Override
......@@ -164,17 +164,17 @@ public class SimpleMastershipStore
}
@Override
public DeviceMastershipTerm getTermFor(DeviceId deviceId) {
public MastershipTerm getTermFor(DeviceId deviceId) {
if ((masterMap.get(deviceId) == null) ||
(termMap.get(deviceId) == null)) {
return null;
}
return DeviceMastershipTerm.of(
return MastershipTerm.of(
masterMap.get(deviceId), termMap.get(deviceId).get());
}
@Override
public DeviceMastershipEvent setStandby(NodeId nodeId, DeviceId deviceId) {
public MastershipEvent setStandby(NodeId nodeId, DeviceId deviceId) {
MastershipRole role = getRole(nodeId, deviceId);
synchronized (this) {
switch (role) {
......@@ -185,7 +185,7 @@ public class SimpleMastershipStore
} else {
masterMap.put(deviceId, backup);
termMap.get(deviceId).incrementAndGet();
return new DeviceMastershipEvent(MASTER_CHANGED, deviceId, backup);
return new MastershipEvent(MASTER_CHANGED, deviceId, backup);
}
case STANDBY:
case NONE:
......@@ -215,7 +215,7 @@ public class SimpleMastershipStore
}
@Override
public DeviceMastershipEvent relinquishRole(NodeId nodeId, DeviceId deviceId) {
public MastershipEvent relinquishRole(NodeId nodeId, DeviceId deviceId) {
return setStandby(nodeId, deviceId);
}
......
......@@ -6,9 +6,9 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.DeviceMastershipTerm;
import com.google.common.collect.Sets;
......@@ -16,7 +16,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.onlab.onos.net.MastershipRole.*;
import static org.onlab.onos.net.device.DeviceMastershipEvent.Type.*;
import static org.onlab.onos.cluster.MastershipEvent.Type.*;
/**
* Test for the simple MastershipStore implementation.
......@@ -98,12 +98,12 @@ public class SimpleMastershipStoreTest {
@Test
public void getTermFor() {
put(DID1, N1, true, true);
assertEquals("wrong term", DeviceMastershipTerm.of(N1, 0), sms.getTermFor(DID1));
assertEquals("wrong term", MastershipTerm.of(N1, 0), sms.getTermFor(DID1));
//switch to N2 and back - 2 term switches
sms.setMaster(N2, DID1);
sms.setMaster(N1, DID1);
assertEquals("wrong term", DeviceMastershipTerm.of(N1, 2), sms.getTermFor(DID1));
assertEquals("wrong term", MastershipTerm.of(N1, 2), sms.getTermFor(DID1));
}
@Test
......
......@@ -20,10 +20,11 @@
<bundle>mvn:io.dropwizard.metrics/metrics-core/3.1.0</bundle>
<bundle>mvn:com.eclipsesource.minimal-json/minimal-json/0.9.1</bundle>
<bundle>mvn:com.esotericsoftware.kryo/kryo/2.24.0</bundle>
<bundle>mvn:com.esotericsoftware/kryo/3.0.0</bundle>
<bundle>mvn:com.esotericsoftware/reflectasm/1.10.0</bundle>
<bundle>mvn:org.ow2.asm/asm/4.2</bundle>
<bundle>mvn:com.esotericsoftware/minlog/1.3.0</bundle>
<bundle>mvn:org.objenesis/objenesis/2.1</bundle>
<bundle>mvn:de.javakaffee/kryo-serializers/0.27</bundle>
<bundle>mvn:org.onlab.onos/onlab-nio/1.0.0-SNAPSHOT</bundle>
......
......@@ -30,7 +30,7 @@
<groupId>org.projectfloodlight</groupId>
<artifactId>openflowj</artifactId>
<!-- FIXME once experimenter gets merged to upstream -->
<version>0.3.8-optical_experimenter</version>
<version>0.3.8-optical_experimenter2</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
......
......@@ -981,13 +981,13 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
// switch was a duplicate-dpid, calling the method below would clear
// all state for the original switch (with the same dpid),
// which we obviously don't want.
log.info("{}:removal called");
log.info("{}:removal called", getSwitchInfoString());
sw.removeConnectedSwitch();
} else {
// A duplicate was disconnected on this ChannelHandler,
// this is the same switch reconnecting, but the original state was
// not cleaned up - XXX check liveness of original ChannelHandler
log.info("{}:duplicate found");
log.info("{}:duplicate found", getSwitchInfoString());
duplicateDpidFound = Boolean.FALSE;
}
} else {
......
......@@ -57,6 +57,12 @@ public final class DriverManager implements OpenFlowSwitchDriverFactory {
}
}
String sw = desc.getSwDesc();
if (sw.startsWith("LINC-OE")) {
log.debug("Optical Emulator LINC-OE with DPID:{} found..", dpid);
return new OFOpticalSwitchImplLINC13(dpid, desc);
}
log.warn("DriverManager could not identify switch desc: {}. "
+ "Assigning AbstractOpenFlowSwich", desc);
return new AbstractOpenFlowSwitch(dpid, desc) {
......
package org.onlab.onos.openflow.drivers.impl;
import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
import org.onlab.onos.openflow.controller.Dpid;
import org.onlab.onos.openflow.controller.driver.AbstractOpenFlowSwitch;
import org.projectfloodlight.openflow.protocol.OFCircuitPortsReply;
import org.projectfloodlight.openflow.protocol.OFCircuitPortsRequest;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFErrorMsg;
import org.projectfloodlight.openflow.protocol.OFMatchV3;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFOxmList;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortOptical;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmInPort;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigid;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigidBasic;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigtype;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigtypeBasic;
import org.projectfloodlight.openflow.types.CircuitSignalID;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.U8;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* LINC-OE Optical Emulator switch class.
*/
public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
private final AtomicBoolean driverHandshakeComplete;
private long barrierXidToWaitFor = -1;
private final Logger log =
LoggerFactory.getLogger(OFOpticalSwitchImplLINC13.class);
OFOpticalSwitchImplLINC13(Dpid dpid, OFDescStatsReply desc) {
super(dpid);
//setAttribute("optical", "true");
driverHandshakeComplete = new AtomicBoolean(false);
setSwitchDescription(desc);
}
@Override
public String toString() {
return "OFOpticalSwitchImplLINC13 [" + ((channel != null)
? channel.getRemoteAddress() : "?")
+ " DPID[" + ((getStringId() != null) ? getStringId() : "?") + "]]";
}
@Override
public void startDriverHandshake() {
log.debug("Starting driver handshake for sw {}", getStringId());
if (startDriverHandshakeCalled) {
throw new SwitchDriverSubHandshakeAlreadyStarted();
}
startDriverHandshakeCalled = true;
try {
sendHandshakeOFExperimenterPortDescRequest();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public boolean isDriverHandshakeComplete() {
if (!startDriverHandshakeCalled) {
throw new SwitchDriverSubHandshakeNotStarted();
}
return driverHandshakeComplete.get();
}
@Override
public void processDriverHandshakeMessage(OFMessage m) {
if (!startDriverHandshakeCalled) {
throw new SwitchDriverSubHandshakeNotStarted();
}
if (driverHandshakeComplete.get()) {
throw new SwitchDriverSubHandshakeCompleted(m);
}
switch (m.getType()) {
case BARRIER_REPLY:
if (m.getXid() == barrierXidToWaitFor) {
log.debug("LINC-OE Received barrier response");
}
break;
case ERROR:
log.error("Switch {} Error {}", getStringId(), (OFErrorMsg) m);
break;
case FEATURES_REPLY:
break;
case FLOW_REMOVED:
break;
case GET_ASYNC_REPLY:
break;
case PACKET_IN:
break;
case PORT_STATUS:
break;
case QUEUE_GET_CONFIG_REPLY:
break;
case ROLE_REPLY:
break;
case STATS_REPLY:
log.debug("LINC-OE : Received stats reply message {}", m);
processHandshakeOFExperimenterPortDescRequest(
(OFCircuitPortsReply) m);
driverHandshakeComplete.set(true);
/* try {
testMA();
} catch (IOException e) {
e.printStackTrace();
}*/
break;
default:
log.debug("Received message {} during switch-driver " +
"subhandshake " + "from switch {} ... " +
"Ignoring message", m,
getStringId());
}
}
private void processHandshakeOFExperimenterPortDescRequest(
OFCircuitPortsReply sr) {
Collection<OFPortOptical> entries = sr.getEntries();
List<OFPortDesc> ofPortDescList = new ArrayList<>(entries.size());
for (OFPortOptical entry : entries) {
ofPortDescList.add(factory().buildPortDesc().
setPortNo(entry.getPortNo())
.setConfig(entry.getConfig())
.setState(entry.getState())
.setHwAddr(entry.getHwAddr())
.setName(entry.getName())
.build());
}
setPortDescReply(factory().buildPortDescStatsReply().
setEntries(ofPortDescList).build());
}
private void sendHandshakeOFExperimenterPortDescRequest() throws
IOException {
// send multi part message for port description for optical switches
OFCircuitPortsRequest circuitPortsRequest = factory()
.buildCircuitPortsRequest().setXid(getNextTransactionId())
.build();
log.debug("LINC-OE : Sending experimented circuit port stats " +
"message " +
"{}",
circuitPortsRequest.toString());
channel.write(Collections.singletonList(circuitPortsRequest));
}
//todo for testing
public static final U8 SIGNAL_TYPE = U8.of((short) 1);
private void testMA() throws IOException {
log.debug("LINC OE *** Testing MA ");
short lambda = 100;
if (getId() == 0x0000ffffffffff02L) {
final int inport = 10;
final int outport = 20;
//Circuit signal id
CircuitSignalID sigID = getSignalID(lambda);
OFOxmOchSigid fieldSigIDMatch = factory().oxms().ochSigid(sigID);
OFOxmOchSigtype fieldSigType = factory()
.oxms()
.ochSigtype(SIGNAL_TYPE);
OFOxmOchSigidBasic ofOxmOchSigidBasic =
factory().oxms().ochSigidBasic(sigID);
OFOxmOchSigtypeBasic ofOxmOchSigtypeBasic =
factory().oxms().ochSigtypeBasic(SIGNAL_TYPE);
//Match Port
OFOxmInPort fieldPort = factory().oxms()
.inPort(OFPort.of(inport));
OFMatchV3 matchPort =
factory()
.buildMatchV3().
setOxmList(OFOxmList.of(fieldPort,
fieldSigType,
fieldSigIDMatch)).build();
// Set Action outport ,sigType and sigID
List<OFAction> actionList = new ArrayList<>();
OFAction actionOutPort =
factory().actions().output(OFPort.of(outport),
Short.MAX_VALUE);
OFActionCircuit actionCircuit = factory()
.actions()
.circuit(ofOxmOchSigidBasic);
OFActionCircuit setActionSigType = factory()
.actions()
.circuit(ofOxmOchSigtypeBasic);
actionList.add(actionOutPort);
actionList.add(setActionSigType);
actionList.add(actionCircuit);
OFInstruction instructionAction =
factory().instructions().buildApplyActions()
.setActions(actionList)
.build();
List<OFInstruction> instructions =
Collections.singletonList(instructionAction);
OFMessage opticalFlowEntry =
factory().buildFlowAdd()
.setMatch(matchPort)
.setInstructions(instructions)
.setXid(getNextTransactionId())
.build();
log.debug("Adding optical flow in sw {}", getStringId());
List<OFMessage> msglist = new ArrayList<>(1);
msglist.add(opticalFlowEntry);
write(msglist);
} else if (getId() == 0x0000ffffffffff03L) {
final int inport = 21;
final int outport = 22;
//Circuit signal id
CircuitSignalID sigID = getSignalID(lambda);
OFOxmOchSigid fieldSigIDMatch = factory().oxms().ochSigid(sigID);
OFOxmOchSigtype fieldSigType = factory()
.oxms()
.ochSigtype(SIGNAL_TYPE);
OFOxmOchSigidBasic ofOxmOchSigidBasic =
factory().oxms().ochSigidBasic(sigID);
OFOxmOchSigtypeBasic ofOxmOchSigtypeBasic =
factory().oxms().ochSigtypeBasic(SIGNAL_TYPE);
//Match Port,SigType,SigID
OFOxmInPort fieldPort = factory()
.oxms()
.inPort(OFPort.of(inport));
OFMatchV3 matchPort = factory()
.buildMatchV3()
.setOxmList(OFOxmList.of(fieldPort,
fieldSigType,
fieldSigIDMatch))
.build();
// Set Action outport ,SigType, sigID
List<OFAction> actionList = new ArrayList<>();
OFAction actionOutPort =
factory().actions().output(OFPort.of(outport),
Short.MAX_VALUE);
OFActionCircuit setActionSigType = factory()
.actions()
.circuit(ofOxmOchSigtypeBasic);
OFActionCircuit actionCircuit = factory()
.actions()
.circuit(ofOxmOchSigidBasic);
actionList.add(actionOutPort);
actionList.add(setActionSigType);
actionList.add(actionCircuit);
OFInstruction instructionAction =
factory().instructions().buildApplyActions()
.setActions(actionList)
.build();
List<OFInstruction> instructions =
Collections.singletonList(instructionAction);
OFMessage opticalFlowEntry =
factory().buildFlowAdd()
.setMatch(matchPort)
.setInstructions(instructions)
.setXid(getNextTransactionId())
.build();
log.debug("Adding optical flow in sw {}", getStringId());
List<OFMessage> msglist = new ArrayList<>(1);
msglist.add(opticalFlowEntry);
write(msglist);
} else if (getId() == 0x0000ffffffffff04L) {
final int inport = 23;
final int outport = 11;
//Circuit signal id
CircuitSignalID sigID = getSignalID(lambda);
OFOxmOchSigid fieldSigIDMatch = factory().oxms().ochSigid(sigID);
OFOxmOchSigtype fieldSigType = factory()
.oxms()
.ochSigtype(SIGNAL_TYPE);
//Match Port, sig type and sig id
OFOxmInPort fieldPort = factory()
.oxms()
.inPort(OFPort.of(inport));
OFMatchV3 matchPort =
factory().buildMatchV3()
.setOxmList(OFOxmList.of(fieldPort,
fieldSigType,
fieldSigIDMatch))
.build();
// Set Action outport
List<OFAction> actionList = new ArrayList<>();
OFAction actionOutPort =
factory().actions().output(OFPort.of(outport),
Short.MAX_VALUE);
actionList.add(actionOutPort);
OFInstruction instructionAction =
factory().instructions().buildApplyActions()
.setActions(actionList)
.build();
List<OFInstruction> instructions =
Collections.singletonList(instructionAction);
OFMessage opticalFlowEntry =
factory().buildFlowAdd()
.setMatch(matchPort)
.setInstructions(instructions)
.setXid(getNextTransactionId())
.build();
log.debug("Adding optical flow in sw {}", getStringId());
List<OFMessage> msglist = new ArrayList<>(1);
msglist.add(opticalFlowEntry);
write(msglist);
}
}
// Todo remove - for testing purpose only
private static CircuitSignalID getSignalID(short lambda) {
byte myGrid = 1;
byte myCs = 2;
short myCn = lambda;
short mySw = 1;
CircuitSignalID signalID = new CircuitSignalID(myGrid,
myCs,
myCn,
mySw);
return signalID;
}
@Override
public void write(OFMessage msg) {
this.channel.write(msg);
}
@Override
public void write(List<OFMessage> msgs) {
this.channel.write(msgs);
}
@Override
public Boolean supportNxRole() {
return false;
}
}
......@@ -193,9 +193,20 @@
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>com.esotericsoftware.kryo</groupId>
<artifactId>kryo</artifactId>
<version>2.24.0</version>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>reflectasm</artifactId>
<version>1.10.0</version>
<type>bundle</type>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>4.2</version>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
......@@ -207,11 +218,6 @@
<artifactId>objenesis</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>de.javakaffee</groupId>
<artifactId>kryo-serializers</artifactId>
<version>0.27</version>
</dependency>
<!-- ONOS related -->
<dependency>
......@@ -284,6 +290,10 @@
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
</dependency>
</dependencies>
......@@ -434,9 +444,6 @@
<version>3.2</version>
<configuration>
<excludes>
<exclude>**/datastore/serializers/**</exclude>
<exclude>**/edu/stanford/**</exclude>
<exclude>**/net/floodlightcontroller/**</exclude>
</excludes>
<rulesets>
<ruleset>onos/pmd.xml</ruleset>
......@@ -493,7 +500,7 @@
<group>
<title>Core Subsystems</title>
<packages>
org.onlab.onos.cluster.impl:org.onlab.onos.net.device.impl:org.onlab.onos.net.link.impl:org.onlab.onos.net.host.impl:org.onlab.onos.net.topology.impl:org.onlab.onos.net.packet.impl:org.onlab.onos.net.flow.impl:org.onlab.onos.store.trivial.*:org.onlab.onos.net.*.impl:org.onlab.onos.event.impl:org.onlab.onos.store.*:org.onlab.onos.net.intent.impl
org.onlab.onos.impl:org.onlab.onos.cluster.impl:org.onlab.onos.net.device.impl:org.onlab.onos.net.link.impl:org.onlab.onos.net.host.impl:org.onlab.onos.net.topology.impl:org.onlab.onos.net.packet.impl:org.onlab.onos.net.flow.impl:org.onlab.onos.store.trivial.*:org.onlab.onos.net.*.impl:org.onlab.onos.event.impl:org.onlab.onos.store.*:org.onlab.onos.net.intent.impl:org.onlab.onos.net.proxyarp.impl
</packages>
</group>
<group>
......@@ -518,7 +525,7 @@
<group>
<title>Sample Applications</title>
<packages>
org.onlab.onos.tvue:org.onlab.onos.fwd:org.onlab.onos.foo
org.onlab.onos.tvue:org.onlab.onos.fwd:org.onlab.onos.ifwd:org.onlab.onos.mobility:org.onlab.onos.proxyarp:org.onlab.onos.foo
</packages>
</group>
</groups>
......@@ -545,9 +552,6 @@
<version>3.2</version>
<configuration>
<excludes>
<exclude>**/datastore/serializers/**</exclude>
<exclude>**/edu/stanford/**</exclude>
<exclude>**/net/floodlightcontroller/**</exclude>
</excludes>
<rulesets>
<ruleset>onos/pmd.xml</ruleset>
......
package org.onlab.onos.provider.of.host.impl;
import static com.google.common.collect.Sets.newHashSet;
import static org.onlab.onos.net.DeviceId.deviceId;
import static org.onlab.onos.net.PortNumber.portNumber;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Set;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
......@@ -36,6 +29,10 @@ import org.onlab.packet.IpPrefix;
import org.onlab.packet.VlanId;
import org.slf4j.Logger;
import static org.onlab.onos.net.DeviceId.deviceId;
import static org.onlab.onos.net.PortNumber.portNumber;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Provider which uses an OpenFlow controller to detect network
* end-station hosts.
......@@ -58,6 +55,8 @@ public class OpenFlowHostProvider extends AbstractProvider implements HostProvid
private final InternalHostProvider listener = new InternalHostProvider();
private boolean ipLearn = true;
/**
* Creates an OpenFlow host provider.
*/
......@@ -69,7 +68,6 @@ public class OpenFlowHostProvider extends AbstractProvider implements HostProvid
public void activate() {
providerService = providerRegistry.register(this);
controller.addPacketListener(10, listener);
log.info("Started");
}
......@@ -78,7 +76,6 @@ public class OpenFlowHostProvider extends AbstractProvider implements HostProvid
providerRegistry.unregister(this);
controller.removePacketListener(listener);
providerService = null;
log.info("Stopped");
}
......@@ -95,33 +92,33 @@ public class OpenFlowHostProvider extends AbstractProvider implements HostProvid
VlanId vlan = VlanId.vlanId(eth.getVlanID());
ConnectPoint heardOn = new ConnectPoint(deviceId(Dpid.uri(pktCtx.dpid())),
portNumber(pktCtx.inPort()));
portNumber(pktCtx.inPort()));
// If this is not an edge port, bail out.
// If this is not an edge port, bail out.
Topology topology = topologyService.currentTopology();
if (topologyService.isInfrastructure(topology, heardOn)) {
return;
}
HostLocation hloc = new HostLocation(deviceId(Dpid.uri(pktCtx.dpid())),
portNumber(pktCtx.inPort()),
System.currentTimeMillis());
portNumber(pktCtx.inPort()),
System.currentTimeMillis());
HostId hid = HostId.hostId(eth.getSourceMAC(), vlan);
// Potentially a new or moved host
if (eth.getEtherType() == Ethernet.TYPE_ARP) {
ARP arp = (ARP) eth.getPayload();
Set<IpPrefix> ips = newHashSet(IpPrefix.valueOf(arp.getSenderProtocolAddress()));
IpPrefix ip = IpPrefix.valueOf(arp.getSenderProtocolAddress());
HostDescription hdescr =
new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ips);
new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip);
providerService.hostDetected(hid, hdescr);
} else if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
IPv4 ip = (IPv4) eth.getPayload();
Set<IpPrefix> ips = newHashSet(IpPrefix.valueOf(ip.getSourceAddress()));
} else if (ipLearn && eth.getEtherType() == Ethernet.TYPE_IPV4) {
IPv4 pip = (IPv4) eth.getPayload();
IpPrefix ip = IpPrefix.valueOf(pip.getSourceAddress());
HostDescription hdescr =
new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ips);
new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip);
providerService.hostDetected(hid, hdescr);
}
......
......@@ -6,7 +6,7 @@
export ONOS_ROOT=${ONOS_ROOT:-~/onos-next}
# Setup some environmental context for developers
export JAVA_HOME=$(/usr/libexec/java_home -v 1.7)
export JAVA_HOME=${JAVA_HOME:-$(/usr/libexec/java_home -v 1.7)}
export MAVEN=${MAVEN:-~/Applications/apache-maven-3.2.2}
export KARAF=${KARAF:-~/Applications/apache-karaf-3.0.1}
export KARAF_LOG=$KARAF/data/log/karaf.log
......
#!/bin/bash
#------------------------------------------------------------------------------
# Echoes project-level directory if a Java file within is newer than the
# target directory.
......
#!/bin/bash
kpid=$(ps -ef | grep karaf.main.Main | grep -v grep | cut -c10-15 | tr -d ' ')
[ -z "$kpid" ] && echo "No ONOS!" && exit 1
/opt/jprofiler8/bin/jpenable --gui --port=8849 --pid=$kpid
# Local VirtualBox-based single ONOS instance & ONOS mininet box
export ONOS_NIC=192.168.56.*
export OC1="192.168.56.103"
export OCN="192.168.56.103"
export ONOS_FEATURES="webconsole,onos-api,onos-core-trivial,onos-cli,onos-openflow,onos-app-fwd"
......@@ -44,18 +44,10 @@
<artifactId>minimal-json</artifactId>
</dependency>
<dependency>
<groupId>com.esotericsoftware.kryo</groupId>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>minlog</artifactId>
</dependency>
<dependency>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>3.1.0</version>
......
......@@ -22,11 +22,12 @@ import java.util.Arrays;
*
*/
public class MacAddress {
public static final byte[] ZERO_MAC_ADDRESS =
MacAddress.valueOf("00:00:00:00:00:00").getAddress();
public static final byte[] BROADCAST_MAC =
MacAddress.valueOf("ff:ff:ff:ff:ff:ff").getAddress();
public static final MacAddress ZERO = valueOf("00:00:00:00:00:00");
public static final MacAddress BROADCAST = valueOf("ff:ff:ff:ff:ff:ff");
public static final byte[] ZERO_MAC_ADDRESS = ZERO.getAddress();
public static final byte[] BROADCAST_MAC = BROADCAST.getAddress();
public static final int MAC_ADDRESS_LENGTH = 6;
private byte[] address = new byte[MacAddress.MAC_ADDRESS_LENGTH];
......
......@@ -3,12 +3,15 @@ package org.onlab.packet;
/**
* Representation of a VLAN ID.
*/
// FIXME: This will end-up looking like a constant; we should name it 'VlanId', 'IpAddress', 'MacAddress'.
public class VlanId {
private final short value;
// Based on convention used elsewhere? Check and change if needed
public static final short UNTAGGED = (short) 0xffff;
public static final VlanId NONE = VlanId.vlanId(UNTAGGED);
// A VLAN ID is actually 12 bits of a VLAN tag.
public static final short MAX_VLAN = 4095;
......
......@@ -32,10 +32,6 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.javakaffee</groupId>
<artifactId>kryo-serializers</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
......