blob: 7e5efb85f11ed36894fdc18e567c0c3b0c23a107 [file] [log] [blame]
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.net.group;
import org.onosproject.core.GroupId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instruction;
import java.util.List;
import java.util.Objects;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Group bucket implementation. A group bucket is collection of
* instructions that can be performed on a traffic flow. A select
* Group can have one or more Buckets where traffic will be
* processed by a single bucket in the group, based on device
* specific selection algorithm (e.g. hash on some fields of the
* incoming traffic flows or round robin) and hence can contains
* optional weight field to define the weights among the buckets
* in the group. A failover group bucket is associated with a
* specific port or group that controls its liveness.
*/
public final class DefaultGroupBucket implements GroupBucket, StoredGroupBucketEntry {
private final GroupDescription.Type type;
private final TrafficTreatment treatment;
private final short weight;
private final PortNumber watchPort;
private final GroupId watchGroup;
private long packets;
private long bytes;
/**
* Group bucket constructor with the parameters.
*
* @param type group bucket type
* @param treatment traffic treatment associated with group bucket
* @param weight optional weight associated with group bucket
* @param watchPort port that determines the liveness of group bucket
* @param watchGroup group that determines the liveness of group bucket
*/
private DefaultGroupBucket(GroupDescription.Type type,
TrafficTreatment treatment,
short weight,
PortNumber watchPort,
GroupId watchGroup) {
this.type = type;
this.treatment = checkNotNull(treatment);
this.weight = weight;
this.watchPort = watchPort;
this.watchGroup = watchGroup;
}
/**
* Creates indirect group bucket.
*
* @param treatment traffic treatment associated with group bucket
* @return indirect group bucket object
*/
public static GroupBucket createIndirectGroupBucket(
TrafficTreatment treatment) {
return new DefaultGroupBucket(GroupDescription.Type.INDIRECT,
treatment,
(short) -1,
null,
null);
}
/**
* Creates select group bucket with weight as 1.
*
* @param treatment traffic treatment associated with group bucket
* @return select group bucket object
*/
public static GroupBucket createSelectGroupBucket(
TrafficTreatment treatment) {
return new DefaultGroupBucket(GroupDescription.Type.SELECT,
treatment,
(short) 1,
null,
null);
}
/**
* Creates select group bucket with specified weight.
*
* @param treatment traffic treatment associated with group bucket
* @param weight weight associated with group bucket
* @return select group bucket object
*/
public static GroupBucket createSelectGroupBucket(
TrafficTreatment treatment,
short weight) {
if (weight == 0) {
return null;
}
return new DefaultGroupBucket(GroupDescription.Type.SELECT,
treatment,
weight,
null,
null);
}
/**
* Creates failover group bucket with watchport or watchgroup.
*
* @param treatment traffic treatment associated with group bucket
* @param watchPort port that determines the liveness of group bucket
* @param watchGroup group that determines the liveness of group bucket
* @return failover group bucket object
*/
public static GroupBucket createFailoverGroupBucket(
TrafficTreatment treatment,
PortNumber watchPort,
GroupId watchGroup) {
checkArgument(((watchPort != null) || (watchGroup != null)));
return new DefaultGroupBucket(GroupDescription.Type.FAILOVER,
treatment,
(short) -1,
watchPort,
watchGroup);
}
/**
* Creates all group bucket.
*
* @param treatment traffic treatment associated with group bucket
* @return all group bucket object
*/
public static GroupBucket createAllGroupBucket(TrafficTreatment treatment) {
return new DefaultGroupBucket(GroupDescription.Type.ALL,
treatment,
(short) -1,
null,
null);
}
@Override
public GroupDescription.Type type() {
return this.type;
}
/**
* Returns list of Traffic instructions that are part of the bucket.
*
* @return TrafficTreatment Traffic instruction list
*/
@Override
public TrafficTreatment treatment() {
return treatment;
}
/**
* Returns weight of select group bucket.
*
* @return short weight associated with a bucket
*/
@Override
public short weight() {
return weight;
}
/**
* Returns port number used for liveness detection for a
* failover bucket.
*
* @return PortNumber port number used for liveness detection
*/
@Override
public PortNumber watchPort() {
return watchPort;
}
/**
* Returns group identifier used for liveness detection for a
* failover bucket.
*
* @return GroupId group identifier to be used for liveness detection
*/
@Override
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;
List<Instruction> myInstructions = this.treatment.allInstructions();
List<Instruction> theirInstructions = that.treatment.allInstructions();
return Objects.equals(type, that.type) &&
myInstructions.containsAll(theirInstructions) &&
theirInstructions.containsAll(myInstructions);
}
return false;
}
@Override
public boolean hasSameParameters(GroupBucket other) {
return weight == other.weight() &&
Objects.equals(watchPort, other.watchPort()) &&
Objects.equals(watchGroup, other.watchGroup());
}
@Override
public String toString() {
return toStringHelper(this)
.add("type", type)
.add("treatment", treatment)
.add("packets", packets)
.add("bytes", bytes)
.toString();
}
@Override
public long packets() {
return packets;
}
@Override
public long bytes() {
return bytes;
}
@Override
public void setPackets(long packets) {
this.packets = packets;
}
@Override
public void setBytes(long bytes) {
this.bytes = bytes;
}
}