ONOS-895: Group manager implementation
Change-Id: Ie183f722fa39012f8de056961715c325e2388e63
diff --git a/core/api/src/main/java/org/onosproject/core/DefaultGroupId.java b/core/api/src/main/java/org/onosproject/core/DefaultGroupId.java
index 11ca73c..58ae9a9 100644
--- a/core/api/src/main/java/org/onosproject/core/DefaultGroupId.java
+++ b/core/api/src/main/java/org/onosproject/core/DefaultGroupId.java
@@ -37,7 +37,7 @@
@Override
public int id() {
- return 0;
+ return this.id;
}
@Override
diff --git a/core/api/src/main/java/org/onosproject/net/group/DefaultGroup.java b/core/api/src/main/java/org/onosproject/net/group/DefaultGroup.java
index 0e4cac1..eba2c6c 100644
--- a/core/api/src/main/java/org/onosproject/net/group/DefaultGroup.java
+++ b/core/api/src/main/java/org/onosproject/net/group/DefaultGroup.java
@@ -17,7 +17,10 @@
import static org.slf4j.LoggerFactory.getLogger;
+import java.util.Objects;
+
import org.onosproject.core.GroupId;
+import org.onosproject.net.DeviceId;
import org.slf4j.Logger;
/**
@@ -32,6 +35,7 @@
private long life;
private long packets;
private long bytes;
+ private long referenceCount;
private GroupId id;
/**
@@ -47,6 +51,29 @@
this.life = 0;
this.packets = 0;
this.bytes = 0;
+ this.referenceCount = 0;
+ }
+
+ /**
+ * Default group object constructor with the available information
+ * from data plane.
+ *
+ * @param id group identifier
+ * @param deviceId device identifier
+ * @param type type of the group
+ * @param buckets immutable list of group bucket
+ */
+ public DefaultGroup(GroupId id,
+ DeviceId deviceId,
+ GroupDescription.Type type,
+ GroupBuckets buckets) {
+ super(deviceId, type, buckets);
+ this.id = id;
+ this.state = GroupState.PENDING_ADD;
+ this.life = 0;
+ this.packets = 0;
+ this.bytes = 0;
+ this.referenceCount = 0;
}
/**
@@ -139,4 +166,43 @@
this.bytes = bytes;
}
+ @Override
+ public void setReferenceCount(long referenceCount) {
+ this.referenceCount = referenceCount;
+ }
+
+ @Override
+ public long referenceCount() {
+ return referenceCount;
+ }
+
+ /*
+ * The deviceId, type and buckets are used for hash.
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public int hashCode() {
+ return super.hashCode() + Objects.hash(id);
+ }
+
+ /*
+ * The deviceId, groupId, type and buckets should be same.
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultGroup) {
+ DefaultGroup that = (DefaultGroup) obj;
+ return super.equals(obj) &&
+ Objects.equals(id, that.id);
+ }
+ return false;
+ }
}
diff --git a/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java b/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java
index 3fab387..931cc71 100644
--- a/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java
+++ b/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java
@@ -18,6 +18,8 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import java.util.Objects;
+
import org.onosproject.core.GroupId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.TrafficTreatment;
@@ -178,4 +180,36 @@
public GroupId watchGroup() {
return watchGroup;
}
+
+ /*
+ * The type and treatment can change on a given bucket
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hash(type, treatment);
+ }
+
+ /*
+ * The priority and statistics can change on a given treatment and selector
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultGroupBucket) {
+ DefaultGroupBucket that = (DefaultGroupBucket) obj;
+ return Objects.equals(type, that.type) &&
+ this.treatment.instructions().containsAll(that.treatment.instructions()) &&
+ that.treatment.instructions().containsAll(this.treatment.instructions());
+ }
+ return false;
+ }
+
}
diff --git a/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java b/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java
index 25af506..8d374c1 100644
--- a/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java
+++ b/core/api/src/main/java/org/onosproject/net/group/DefaultGroupDescription.java
@@ -17,6 +17,8 @@
import static com.google.common.base.Preconditions.checkNotNull;
+import java.util.Objects;
+
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
@@ -49,8 +51,8 @@
this.type = checkNotNull(type);
this.deviceId = checkNotNull(deviceId);
this.buckets = checkNotNull(buckets);
- this.appCookie = checkNotNull(appCookie);
- this.appId = checkNotNull(appId);
+ this.appCookie = appCookie;
+ this.appId = appId;
}
/**
@@ -61,11 +63,27 @@
*
*/
public DefaultGroupDescription(GroupDescription groupDesc) {
- this.type = checkNotNull(groupDesc.type());
- this.deviceId = checkNotNull(groupDesc.deviceId());
- this.buckets = checkNotNull(groupDesc.buckets());
- this.appCookie = checkNotNull(groupDesc.appCookie());
- this.appId = checkNotNull(groupDesc.appId());
+ this.type = groupDesc.type();
+ this.deviceId = groupDesc.deviceId();
+ this.buckets = groupDesc.buckets();
+ this.appCookie = groupDesc.appCookie();
+ this.appId = groupDesc.appId();
+ }
+
+ /**
+ * Constructor to be used by group subsystem internal components.
+ * Creates group description object from the information retrieved
+ * from data plane.
+ *
+ * @param deviceId device identifier
+ * @param type type of the group
+ * @param buckets immutable list of group bucket
+ *
+ */
+ public DefaultGroupDescription(DeviceId deviceId,
+ GroupDescription.Type type,
+ GroupBuckets buckets) {
+ this(deviceId, type, buckets, null, null);
}
/**
@@ -118,4 +136,36 @@
return this.buckets;
}
+ @Override
+ /*
+ * The deviceId, type and buckets are used for hash.
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public int hashCode() {
+ return Objects.hash(deviceId, type, buckets);
+ }
+
+ @Override
+ /*
+ * The deviceId, type and buckets should be same.
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultGroupDescription) {
+ DefaultGroupDescription that = (DefaultGroupDescription) obj;
+ return Objects.equals(deviceId, that.deviceId) &&
+ Objects.equals(type, that.type) &&
+ Objects.equals(buckets, that.buckets);
+
+ }
+ return false;
+ }
+
}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/group/Group.java b/core/api/src/main/java/org/onosproject/net/group/Group.java
index f7fa507..b7872de 100644
--- a/core/api/src/main/java/org/onosproject/net/group/Group.java
+++ b/core/api/src/main/java/org/onosproject/net/group/Group.java
@@ -26,6 +26,10 @@
*/
public enum GroupState {
/**
+ * Group create request is queued as group AUDIT is in progress.
+ */
+ WAITING_AUDIT_COMPLETE,
+ /**
* Group create request is processed by ONOS and not yet
* received the confirmation from data plane.
*/
@@ -81,4 +85,11 @@
* @return number of bytes
*/
long bytes();
+
+ /**
+ * Returns the number of flow rules or other groups reference this group.
+ *
+ * @return number of flow rules or other groups pointing to this group
+ */
+ long referenceCount();
}
diff --git a/core/api/src/main/java/org/onosproject/net/group/GroupBuckets.java b/core/api/src/main/java/org/onosproject/net/group/GroupBuckets.java
index 10f4eca..5ca8f30 100644
--- a/core/api/src/main/java/org/onosproject/net/group/GroupBuckets.java
+++ b/core/api/src/main/java/org/onosproject/net/group/GroupBuckets.java
@@ -45,4 +45,25 @@
return buckets;
}
+ @Override
+ public int hashCode() {
+ int result = 17;
+ int combinedHash = 0;
+ for (GroupBucket bucket:buckets) {
+ combinedHash = combinedHash + bucket.hashCode();
+ }
+ result = 31 * result + combinedHash;
+
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof GroupBuckets) {
+ return (this.buckets.containsAll(((GroupBuckets) obj).buckets) &&
+ ((GroupBuckets) obj).buckets.containsAll(this.buckets));
+ }
+ return false;
+ }
+
}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/group/GroupOperation.java b/core/api/src/main/java/org/onosproject/net/group/GroupOperation.java
index 44d7e88..5a66aca 100644
--- a/core/api/src/main/java/org/onosproject/net/group/GroupOperation.java
+++ b/core/api/src/main/java/org/onosproject/net/group/GroupOperation.java
@@ -17,6 +17,8 @@
import static com.google.common.base.Preconditions.checkNotNull;
+import java.util.Objects;
+
import org.onosproject.core.GroupId;
/**
@@ -142,4 +144,37 @@
public GroupBuckets buckets() {
return this.buckets;
}
+
+ @Override
+ /*
+ * The deviceId, type and buckets are used for hash.
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public int hashCode() {
+ return (buckets != null) ? Objects.hash(groupId, opType, buckets) :
+ Objects.hash(groupId, opType);
+ }
+
+ @Override
+ /*
+ * The deviceId, type and buckets should be same.
+ *
+ * (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof GroupOperation) {
+ GroupOperation that = (GroupOperation) obj;
+ return Objects.equals(groupId, that.groupId) &&
+ Objects.equals(opType, that.opType) &&
+ Objects.equals(buckets, that.buckets);
+
+ }
+ return false;
+ }
}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/group/GroupProviderRegistry.java b/core/api/src/main/java/org/onosproject/net/group/GroupProviderRegistry.java
new file mode 100644
index 0000000..d45789d
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/group/GroupProviderRegistry.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.group;
+
+import org.onosproject.net.provider.ProviderRegistry;
+
+/**
+ * Abstraction for a group provider registry.
+ */
+public interface GroupProviderRegistry
+ extends ProviderRegistry<GroupProvider, GroupProviderService> {
+}
diff --git a/core/api/src/main/java/org/onosproject/net/group/GroupService.java b/core/api/src/main/java/org/onosproject/net/group/GroupService.java
index 1fd9984..8502aea 100644
--- a/core/api/src/main/java/org/onosproject/net/group/GroupService.java
+++ b/core/api/src/main/java/org/onosproject/net/group/GroupService.java
@@ -16,7 +16,6 @@
package org.onosproject.net.group;
import org.onosproject.core.ApplicationId;
-import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
/**
@@ -27,7 +26,7 @@
* specified in a group.
* "group" can also be used for grouping common actions of different flows,
* so that in some scenarios only one group entry required to be modified
- * for all the referencing flow entries instead of modifying all of them
+ * for all the referencing flow entries instead of modifying all of them.
*
* This implements semantics of a distributed authoritative group store
* where the master copy of the groups lies with the controller and
@@ -60,7 +59,7 @@
* NOTE1: The presence of group object in the system does not
* guarantee that the "group" is actually created in device.
* GROUP_ADDED notification would confirm the creation of
- * this group in data plane
+ * this group in data plane.
*
* @param deviceId device identifier
* @param appCookie application cookie to be used for lookup
@@ -73,7 +72,7 @@
* Appends buckets to existing group. The caller can optionally
* associate a new cookie during this updation. GROUP_UPDATED or
* GROUP_UPDATE_FAILED notifications would be provided along with
- * cookie depending on the result of the operation on the device
+ * cookie depending on the result of the operation on the device.
*
* @param deviceId device identifier
* @param oldCookie cookie to be used to retrieve the existing group
@@ -91,7 +90,7 @@
* Removes buckets from existing group. The caller can optionally
* associate a new cookie during this updation. GROUP_UPDATED or
* GROUP_UPDATE_FAILED notifications would be provided along with
- * cookie depending on the result of the operation on the device
+ * cookie depending on the result of the operation on the device.
*
* @param deviceId device identifier
* @param oldCookie cookie to be used to retrieve the existing group
@@ -99,7 +98,7 @@
* @param newCookie immutable cookie to be used post update operation
* @param appId Application Id
*/
- void removeBucketsFromGroup(Device deviceId,
+ void removeBucketsFromGroup(DeviceId deviceId,
GroupKey oldCookie,
GroupBuckets buckets,
GroupKey newCookie,
@@ -109,13 +108,13 @@
* Deletes a group associated to an application cookie.
* GROUP_DELETED or GROUP_DELETE_FAILED notifications would be
* provided along with cookie depending on the result of the
- * operation on the device
+ * operation on the device.
*
* @param deviceId device identifier
* @param appCookie application cookie to be used for lookup
* @param appId Application Id
*/
- void removeGroup(Device deviceId, GroupKey appCookie, ApplicationId appId);
+ void removeGroup(DeviceId deviceId, GroupKey appCookie, ApplicationId appId);
/**
* Retrieves all groups created by an application in the specified device
@@ -125,7 +124,7 @@
* @param appId application id
* @return collection of immutable group objects created by the application
*/
- Iterable<Group> getGroups(Device deviceId, ApplicationId appId);
+ Iterable<Group> getGroups(DeviceId deviceId, ApplicationId appId);
/**
* Adds the specified group listener.
diff --git a/core/api/src/main/java/org/onosproject/net/group/GroupStore.java b/core/api/src/main/java/org/onosproject/net/group/GroupStore.java
index 22914f9..2fc7030 100644
--- a/core/api/src/main/java/org/onosproject/net/group/GroupStore.java
+++ b/core/api/src/main/java/org/onosproject/net/group/GroupStore.java
@@ -73,12 +73,14 @@
* @param deviceId the device ID
* @param oldAppCookie the current group key
* @param type update type
- * @param newGroupDesc group description with updates
+ * @param newBuckets group buckets for updates
+ * @param newAppCookie optional new group key
*/
void updateGroupDescription(DeviceId deviceId,
GroupKey oldAppCookie,
UpdateType type,
- GroupDescription newGroupDesc);
+ GroupBuckets newBuckets,
+ GroupKey newAppCookie);
/**
* Triggers deleting the existing group entry.
@@ -102,4 +104,43 @@
* @param group group entry
*/
void removeGroupEntry(Group group);
+
+ /**
+ * A group entry that is present in switch but not in the store.
+ *
+ * @param group group entry
+ */
+ void addOrUpdateExtraneousGroupEntry(Group group);
+
+ /**
+ * Remove the group entry from extraneous database.
+ *
+ * @param group group entry
+ */
+ void removeExtraneousGroupEntry(Group group);
+
+ /**
+ * Returns the extraneous groups associated with a device.
+ *
+ * @param deviceId the device ID
+ *
+ * @return the extraneous group entries
+ */
+ Iterable<Group> getExtraneousGroups(DeviceId deviceId);
+
+ /**
+ * Indicates the first group audit is completed.
+ *
+ * @param deviceId the device ID
+ */
+ void deviceInitialAuditCompleted(DeviceId deviceId);
+
+ /**
+ * Retrieves the initial group audit status for a device.
+ *
+ * @param deviceId the device ID
+ *
+ * @return initial group audit status
+ */
+ boolean deviceInitialAuditStatus(DeviceId deviceId);
}
diff --git a/core/api/src/main/java/org/onosproject/net/group/StoredGroupEntry.java b/core/api/src/main/java/org/onosproject/net/group/StoredGroupEntry.java
index b3557b4..297663f 100644
--- a/core/api/src/main/java/org/onosproject/net/group/StoredGroupEntry.java
+++ b/core/api/src/main/java/org/onosproject/net/group/StoredGroupEntry.java
@@ -49,4 +49,10 @@
*/
void setBytes(long bytes);
+ /**
+ * Sets number of flow rules or groups referencing this group entry.
+ *
+ * @param referenceCount reference count
+ */
+ void setReferenceCount(long referenceCount);
}