Introduced HOST_AUX_MOVED event
Additionally,
- Fixed an issue in DistributedHostStore that didn't copy innverVlan, tpid and suspend bit correctly in some cases
- Clarified javadoc of getConnectedHosts
Change-Id: I56c93eea878a24a6588ceecdbeac75c1747ae8cc
diff --git a/core/api/src/main/java/org/onosproject/net/host/DefaultHostDescription.java b/core/api/src/main/java/org/onosproject/net/host/DefaultHostDescription.java
index c83c2c1..74fa9f4 100644
--- a/core/api/src/main/java/org/onosproject/net/host/DefaultHostDescription.java
+++ b/core/api/src/main/java/org/onosproject/net/host/DefaultHostDescription.java
@@ -18,6 +18,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
+import java.util.Objects;
import java.util.Set;
import org.onlab.packet.EthType;
@@ -31,7 +32,6 @@
import com.google.common.collect.ImmutableSet;
import static com.google.common.base.MoreObjects.toStringHelper;
-import com.google.common.base.Objects;
/**
* Default implementation of an immutable host description.
@@ -42,6 +42,7 @@
private final MacAddress mac;
private final VlanId vlan;
private final Set<HostLocation> locations;
+ private final Set<HostLocation> auxLocations;
private final Set<IpAddress> ip;
private final VlanId innerVlan;
private final EthType tpid;
@@ -157,10 +158,31 @@
public DefaultHostDescription(MacAddress mac, VlanId vlan, Set<HostLocation> locations,
Set<IpAddress> ip, VlanId innerVlan, EthType tpid,
boolean configured, SparseAnnotations... annotations) {
+ this(mac, vlan, locations, null, ip, innerVlan, tpid, configured, annotations);
+ }
+
+ /**
+ * Creates a host description using the supplied information.
+ *
+ * @param mac host MAC address
+ * @param vlan host VLAN identifier
+ * @param locations host locations
+ * @param auxLocations set of auxiliary locations, or null if unspecified
+ * @param ip host IP address
+ * @param innerVlan host inner VLAN identifier
+ * @param tpid outer TPID of a host
+ * @param configured true if configured via NetworkConfiguration
+ * @param annotations optional key/value annotations map
+ */
+ public DefaultHostDescription(MacAddress mac, VlanId vlan,
+ Set<HostLocation> locations, Set<HostLocation> auxLocations,
+ Set<IpAddress> ip, VlanId innerVlan, EthType tpid,
+ boolean configured, SparseAnnotations... annotations) {
super(annotations);
this.mac = mac;
this.vlan = vlan;
this.locations = new HashSet<>(locations);
+ this.auxLocations = (auxLocations != null) ? new HashSet<>(auxLocations) : null;
this.ip = new HashSet<>(ip);
this.innerVlan = innerVlan;
this.tpid = tpid;
@@ -212,6 +234,11 @@
}
@Override
+ public Set<HostLocation> auxLocations() {
+ return auxLocations;
+ }
+
+ @Override
public Set<IpAddress> ipAddress() {
return ip;
}
@@ -237,6 +264,7 @@
.add("mac", mac)
.add("vlan", vlan)
.add("locations", locations)
+ .add("auxLocations", auxLocations)
.add("ipAddress", ip)
.add("configured", configured)
.add("innerVlanId", innerVlan)
@@ -246,7 +274,7 @@
@Override
public int hashCode() {
- return Objects.hashCode(super.hashCode(), mac, vlan, locations, ip);
+ return Objects.hash(super.hashCode(), mac, vlan, locations, auxLocations, ip);
}
@Override
@@ -256,12 +284,13 @@
return false;
}
DefaultHostDescription that = (DefaultHostDescription) object;
- return Objects.equal(this.mac, that.mac)
- && Objects.equal(this.vlan, that.vlan)
- && Objects.equal(this.locations, that.locations)
- && Objects.equal(this.ip, that.ip)
- && Objects.equal(this.innerVlan, that.innerVlan)
- && Objects.equal(this.tpid, that.tpid);
+ return Objects.equals(this.mac, that.mac)
+ && Objects.equals(this.vlan, that.vlan)
+ && Objects.equals(this.locations, that.locations)
+ && Objects.equals(this.auxLocations, that.auxLocations)
+ && Objects.equals(this.ip, that.ip)
+ && Objects.equals(this.innerVlan, that.innerVlan)
+ && Objects.equals(this.tpid, that.tpid);
}
return false;
}
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostDescription.java b/core/api/src/main/java/org/onosproject/net/host/HostDescription.java
index 543836e..322b57d 100644
--- a/core/api/src/main/java/org/onosproject/net/host/HostDescription.java
+++ b/core/api/src/main/java/org/onosproject/net/host/HostDescription.java
@@ -76,6 +76,13 @@
Set<HostLocation> locations();
/**
+ * Returns host auxiliary locations, which could be useful for app operations in addition to the attach points.
+ *
+ * @return auxiliary locations, or null if unspecified
+ */
+ Set<HostLocation> auxLocations();
+
+ /**
* Returns the IP address associated with this host's MAC.
*
* @return host IP address
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostEvent.java b/core/api/src/main/java/org/onosproject/net/host/HostEvent.java
index 0fecf2b..132ac11 100644
--- a/core/api/src/main/java/org/onosproject/net/host/HostEvent.java
+++ b/core/api/src/main/java/org/onosproject/net/host/HostEvent.java
@@ -56,7 +56,11 @@
/**
* Signifies that host state in non offending state.
*/
- HOST_UNSUSPENDED
+ HOST_UNSUSPENDED,
+ /**
+ * Signifies that host auxiliary location has changed.
+ */
+ HOST_AUX_MOVED
}
private Host prevSubject;
@@ -94,7 +98,7 @@
*/
public HostEvent(Type type, Host host, Host prevSubject) {
super(type, host);
- if (type == Type.HOST_MOVED || type == Type.HOST_UPDATED) {
+ if (type == Type.HOST_MOVED || type == Type.HOST_UPDATED || type == Type.HOST_AUX_MOVED) {
this.prevSubject = prevSubject;
}
}
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostService.java b/core/api/src/main/java/org/onosproject/net/host/HostService.java
index 55532bc..349f6db 100644
--- a/core/api/src/main/java/org/onosproject/net/host/HostService.java
+++ b/core/api/src/main/java/org/onosproject/net/host/HostService.java
@@ -81,8 +81,7 @@
// TODO: consider adding Host getHostByIp(IpAddress ip, VlanId vlan);
/**
- * Returns the set of hosts whose most recent location is the specified
- * connection point.
+ * Returns the set of hosts that attach to the specified connection point.
*
* @param connectPoint connection point
* @return set of hosts connected to the connection point
@@ -90,8 +89,7 @@
Set<Host> getConnectedHosts(ConnectPoint connectPoint);
/**
- * Returns the set of hosts whose most recent location is the specified
- * infrastructure device.
+ * Returns the set of hosts that attach to the specified device.
*
* @param deviceId device identifier
* @return set of hosts connected to the device
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostStore.java b/core/api/src/main/java/org/onosproject/net/host/HostStore.java
index 6d6eb11..b6b27b5 100644
--- a/core/api/src/main/java/org/onosproject/net/host/HostStore.java
+++ b/core/api/src/main/java/org/onosproject/net/host/HostStore.java
@@ -127,7 +127,7 @@
Set<Host> getHosts(IpAddress ip);
/**
- * Returns the set of hosts whose location falls on the given connection point.
+ * Returns the set of hosts that attach to the specified connection point.
*
* @param connectPoint connection point
* @return set of hosts
@@ -135,7 +135,7 @@
Set<Host> getConnectedHosts(ConnectPoint connectPoint);
/**
- * Returns the set of hosts whose location falls on the given device.
+ * Returns the set of hosts that attach to the specified device.
*
* @param deviceId infrastructure device identifier
* @return set of hosts
diff --git a/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java b/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java
index c4e1b68..c68cee3 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java
@@ -155,7 +155,8 @@
!Objects.equals(existingHost.vlan(), hostDescription.vlan()) ||
!Objects.equals(existingHost.innerVlan(), hostDescription.innerVlan()) ||
!Objects.equals(existingHost.tpid(), hostDescription.tpid()) ||
- !Objects.equals(existingHost.locations(), hostDescription.locations())) {
+ !Objects.equals(existingHost.locations(), hostDescription.locations()) ||
+ !Objects.equals(existingHost.auxLocations(), hostDescription.auxLocations())) {
return true;
}
@@ -211,10 +212,12 @@
hostDescription.hwAddress(),
hostDescription.vlan(),
hostDescription.locations(),
+ hostDescription.auxLocations(),
addresses,
hostDescription.innerVlan(),
hostDescription.tpid(),
hostDescription.configured(),
+ false,
annotations);
});
return null;
@@ -247,6 +250,7 @@
existingHost.mac(),
existingHost.vlan(),
existingHost.locations(),
+ existingHost.auxLocations(),
ImmutableSet.copyOf(addresses),
existingHost.innerVlan(),
existingHost.tpid(),
@@ -280,7 +284,7 @@
return new DefaultHost(existingHost.providerId(),
hostId, existingHost.mac(), existingHost.vlan(),
- newLocations, existingHost.ipAddresses(),
+ newLocations, existingHost.auxLocations(), existingHost.ipAddresses(),
existingHost.innerVlan(), existingHost.tpid(),
existingHost.configured(), existingHost.suspended(), existingHost.annotations());
}
@@ -305,7 +309,7 @@
return locations.isEmpty() ? null :
new DefaultHost(existingHost.providerId(),
hostId, existingHost.mac(), existingHost.vlan(),
- locations, existingHost.ipAddresses(),
+ locations, existingHost.auxLocations(), existingHost.ipAddresses(),
existingHost.innerVlan(), existingHost.tpid(),
existingHost.configured(), existingHost.suspended(), existingHost.annotations());
}
@@ -373,6 +377,7 @@
existingHost.mac(),
existingHost.vlan(),
existingHost.locations(),
+ existingHost.auxLocations(),
existingHost.ipAddresses(),
existingHost.innerVlan(),
existingHost.tpid(),
@@ -396,6 +401,7 @@
existingHost.mac(),
existingHost.vlan(),
existingHost.locations(),
+ existingHost.auxLocations(),
existingHost.ipAddresses(),
existingHost.innerVlan(),
existingHost.tpid(),
@@ -474,6 +480,8 @@
notifyDelegate(new HostEvent(HOST_UNSUSPENDED, host, prevHost));
} else if (!Objects.equals(prevHost.locations(), host.locations())) {
notifyDelegate(new HostEvent(HOST_MOVED, host, prevHost));
+ } else if (!Objects.equals(prevHost.auxLocations(), host.auxLocations())) {
+ notifyDelegate(new HostEvent(HOST_AUX_MOVED, host, prevHost));
} else if (!Objects.equals(prevHost, host)) {
notifyDelegate(new HostEvent(HOST_UPDATED, host, prevHost));
}
diff --git a/core/store/dist/src/test/java/org/onosproject/store/host/impl/DistributedHostStoreTest.java b/core/store/dist/src/test/java/org/onosproject/store/host/impl/DistributedHostStoreTest.java
index a8caf2d..18e8a26 100644
--- a/core/store/dist/src/test/java/org/onosproject/store/host/impl/DistributedHostStoreTest.java
+++ b/core/store/dist/src/test/java/org/onosproject/store/host/impl/DistributedHostStoreTest.java
@@ -19,8 +19,10 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.onlab.packet.EthType;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DeviceId;
@@ -30,6 +32,8 @@
import org.onosproject.net.PortNumber;
import org.onosproject.net.host.DefaultHostDescription;
import org.onosproject.net.host.HostDescription;
+import org.onosproject.net.host.HostEvent;
+import org.onosproject.net.host.HostStoreDelegate;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.store.service.MapEvent;
import org.onosproject.store.service.TestStorageService;
@@ -50,6 +54,7 @@
public class DistributedHostStoreTest {
private DistributedHostStore ecXHostStore;
+ private TestStoreDelegate delegate;
private static final HostId HOSTID = HostId.hostId(MacAddress.valueOf("1a:1a:1a:1a:1a:1a"));
private static final HostId HOSTID1 = HostId.hostId(MacAddress.valueOf("1a:1a:1a:1a:1a:1b"));
@@ -97,11 +102,30 @@
HOST_LEARNT_WITH_ADDRESSES.annotations());
private static final MapEvent<HostId, DefaultHost> HOST_EVENT =
new MapEvent<>("foobar", HOSTID, new Versioned<>(NEW_HOST, 0), new Versioned<>(OLD_HOST, 0));
+ private static final DefaultHost HOST1 = new DefaultHost(PID, HOSTID, HOSTID.mac(), HOSTID.vlanId(),
+ Set.<HostLocation>of(HOST_LOC11), null,
+ Set.<IpAddress>of(), VlanId.NONE,
+ EthType.EtherType.UNKNOWN.ethType(), false, false);
+ private static final DefaultHost HOST2 = new DefaultHost(PID, HOSTID, HOSTID.mac(), HOSTID.vlanId(),
+ Set.<HostLocation>of(HOST_LOC11), null,
+ Set.<IpAddress>of(IP1), VlanId.NONE,
+ EthType.EtherType.UNKNOWN.ethType(), false, false);
+ private static final DefaultHost HOST3 = new DefaultHost(PID, HOSTID, HOSTID.mac(), HOSTID.vlanId(),
+ Set.<HostLocation>of(HOST_LOC11, HOST_LOC12), null,
+ Set.<IpAddress>of(IP1), VlanId.NONE,
+ EthType.EtherType.UNKNOWN.ethType(), false, false);
+ private static final DefaultHost HOST4 = new DefaultHost(PID, HOSTID, HOSTID.mac(), HOSTID.vlanId(),
+ Set.<HostLocation>of(HOST_LOC11), Set.<HostLocation>of(HOST_LOC12),
+ Set.<IpAddress>of(IP1), VlanId.NONE,
+ EthType.EtherType.UNKNOWN.ethType(), false, false);
@Before
public void setUp() {
ecXHostStore = new DistributedHostStore();
+ delegate = new TestStoreDelegate();
+ ecXHostStore.setDelegate(delegate);
+
ecXHostStore.storageService = new TestStorageService();
ecXHostStore.activate();
}
@@ -299,6 +323,74 @@
assertEquals(HOST_ADDRESS, hostInHostsByIp.ipAddresses());
}
+ @Test
+ public void testHostAdded() {
+ // Host is first discovered at only one location
+ MapEvent<HostId, DefaultHost> event = new MapEvent<>("event", HOSTID,
+ new Versioned<>(HOST1, 0), null);
+ // Expect: HOST_ADDED
+ ecXHostStore.hostLocationTracker.event(event);
+ assertEquals(HostEvent.Type.HOST_ADDED, delegate.lastEvent.type());
+ assertEquals(HOST1, delegate.lastEvent.subject());
+ assertNull(delegate.lastEvent.prevSubject());
+ }
+
+ @Test
+ public void testHostUpdated() {
+ // Host is updated with an IP
+ MapEvent<HostId, DefaultHost> event = new MapEvent<>("event", HOSTID,
+ new Versioned<>(HOST2, 1), new Versioned<>(HOST1, 0));
+ // Expect: HOST_UPDATED
+ ecXHostStore.hostLocationTracker.event(event);
+ assertEquals(HostEvent.Type.HOST_UPDATED, delegate.lastEvent.type());
+ assertEquals(HOST2, delegate.lastEvent.subject());
+ assertEquals(HOST1, delegate.lastEvent.prevSubject());
+ }
+
+ @Test
+ public void testHostMoved() {
+ // Host is updated with a second location
+ MapEvent<HostId, DefaultHost> event = new MapEvent<>("event", HOSTID,
+ new Versioned<>(HOST3, 1), new Versioned<>(HOST2, 0));
+ // Expect: HOST_MOVED
+ ecXHostStore.hostLocationTracker.event(event);
+ assertEquals(HostEvent.Type.HOST_MOVED, delegate.lastEvent.type());
+ assertEquals(HOST3, delegate.lastEvent.subject());
+ assertEquals(HOST2, delegate.lastEvent.prevSubject());
+ }
+
+ @Test
+ public void testHostAuxMoved() {
+ // Host aux location changed
+ MapEvent<HostId, DefaultHost> event = new MapEvent<>("event", HOSTID,
+ new Versioned<>(HOST4, 1), new Versioned<>(HOST1, 0));
+ // Expect: HOST_AUX_MOVED
+ ecXHostStore.hostLocationTracker.event(event);
+ assertEquals(HostEvent.Type.HOST_AUX_MOVED, delegate.lastEvent.type());
+ assertEquals(HOST4, delegate.lastEvent.subject());
+ assertEquals(HOST1, delegate.lastEvent.prevSubject());
+ }
+
+ @Test
+ public void testHostRemoved() {
+ // Host is removed
+ MapEvent<HostId, DefaultHost> event = new MapEvent<>("event", HOSTID,
+ null, new Versioned<>(HOST3, 0));
+ // Expect: HOST_REMOVED
+ ecXHostStore.hostLocationTracker.event(event);
+ assertEquals(HostEvent.Type.HOST_REMOVED, delegate.lastEvent.type());
+ assertEquals(HOST3, delegate.lastEvent.subject());
+ assertNull(delegate.lastEvent.prevSubject());
+ }
+
+ private class TestStoreDelegate implements HostStoreDelegate {
+ public HostEvent lastEvent;
+
+ @Override
+ public void notify(HostEvent event) {
+ lastEvent = event;
+ }
+ }
private static HostDescription createHostDesc(HostId hostId, Set<IpAddress> ips) {
return createHostDesc(hostId, ips, false, Collections.emptySet());