blob: 81c0638c265b408f02ae829d4b64bc975d1bfa4a [file] [log] [blame]
/*
* Copyright 2014-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.flow;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.DefaultGroupId;
import org.onosproject.core.GroupId;
import org.onosproject.net.DeviceId;
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;
public class DefaultFlowRule implements FlowRule {
private final DeviceId deviceId;
private final int priority;
private final TrafficSelector selector;
private final TrafficTreatment treatment;
private final long created;
private final FlowId id;
private final Short appId;
private final int timeout;
private final boolean permanent;
private final GroupId groupId;
private final Integer tableId;
@Deprecated
public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
TrafficTreatment treatment, int priority, long flowId,
int timeout, boolean permanent) {
this.deviceId = deviceId;
this.priority = priority;
this.selector = selector;
this.treatment = treatment;
this.timeout = timeout;
this.permanent = permanent;
this.created = System.currentTimeMillis();
this.appId = (short) (flowId >>> 48);
this.groupId = new DefaultGroupId((short) ((flowId >>> 32) & 0xFFFF));
this.id = FlowId.valueOf(flowId);
this.tableId = 0;
}
@Deprecated
public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
TrafficTreatment treatment, int priority, long flowId,
int timeout, boolean permanent, Type tableType) {
this.deviceId = deviceId;
this.priority = priority;
this.selector = selector;
this.treatment = treatment;
this.timeout = timeout;
this.permanent = permanent;
this.created = System.currentTimeMillis();
this.appId = (short) (flowId >>> 48);
this.groupId = new DefaultGroupId((short) ((flowId >>> 32) & 0xFFFF));
this.id = FlowId.valueOf(flowId);
this.tableId = tableType.ordinal();
}
@Deprecated
public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
TrafficTreatment treatment, int priority, ApplicationId appId,
int timeout, boolean permanent) {
this(deviceId, selector, treatment, priority, appId, new DefaultGroupId(0),
timeout, permanent);
}
@Deprecated
public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
TrafficTreatment treatment, int priority, ApplicationId appId,
int timeout, boolean permanent, Type type) {
if (priority < FlowRule.MIN_PRIORITY) {
throw new IllegalArgumentException("Priority cannot be less than " + MIN_PRIORITY);
}
this.deviceId = deviceId;
this.priority = priority;
this.selector = selector;
this.treatment = treatment;
this.appId = appId.id();
this.groupId = new DefaultGroupId(0);
this.timeout = timeout;
this.permanent = permanent;
this.created = System.currentTimeMillis();
this.tableId = type.ordinal();
/*
* id consists of the following.
* | appId (16 bits) | groupId (16 bits) | flowId (32 bits) |
*/
this.id = FlowId.valueOf((((long) this.appId) << 48) | (((long) this.groupId.id()) << 32)
| (this.hash() & 0xffffffffL));
}
@Deprecated
public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
TrafficTreatment treatment, int priority, ApplicationId appId,
GroupId groupId, int timeout, boolean permanent) {
if (priority < FlowRule.MIN_PRIORITY) {
throw new IllegalArgumentException("Priority cannot be less than " + MIN_PRIORITY);
}
this.deviceId = deviceId;
this.priority = priority;
this.selector = selector;
this.treatment = treatment;
this.appId = appId.id();
this.groupId = groupId;
this.timeout = timeout;
this.permanent = permanent;
this.created = System.currentTimeMillis();
this.tableId = 0;
/*
* id consists of the following.
* | appId (16 bits) | groupId (16 bits) | flowId (32 bits) |
*/
this.id = FlowId.valueOf((((long) this.appId) << 48) | (((long) this.groupId.id()) << 32)
| (this.hash() & 0xffffffffL));
}
public DefaultFlowRule(FlowRule rule) {
this.deviceId = rule.deviceId();
this.priority = rule.priority();
this.selector = rule.selector();
this.treatment = rule.treatment();
this.appId = rule.appId();
this.groupId = rule.groupId();
this.id = rule.id();
this.timeout = rule.timeout();
this.permanent = rule.isPermanent();
this.created = System.currentTimeMillis();
this.tableId = rule.tableId();
}
private DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
TrafficTreatment treatment, Integer priority,
FlowId flowId, Boolean permanent, Integer timeout,
Integer tableId) {
this.deviceId = deviceId;
this.selector = selector;
this.treatment = treatment;
this.priority = priority;
this.appId = (short) (flowId.value() >>> 48);
this.id = flowId;
this.permanent = permanent;
this.timeout = timeout;
this.tableId = tableId;
this.created = System.currentTimeMillis();
//FIXME: fields below will be removed.
this.groupId = null;
}
@Override
public FlowId id() {
return id;
}
@Override
public short appId() {
return appId;
}
@Override
public GroupId groupId() {
return groupId;
}
@Override
public int priority() {
return priority;
}
@Override
public DeviceId deviceId() {
return deviceId;
}
@Override
public TrafficSelector selector() {
return selector;
}
@Override
public TrafficTreatment treatment() {
return treatment;
}
@Override
/*
* The priority and statistics can change on a given treatment and selector
*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public int hashCode() {
return Objects.hash(deviceId, selector, priority, tableId);
}
public int hash() {
return Objects.hash(deviceId, selector, treatment, tableId);
}
@Override
/*
* The priority and statistics can change on a given treatment and selector
*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultFlowRule) {
DefaultFlowRule that = (DefaultFlowRule) obj;
return Objects.equals(deviceId, that.deviceId) &&
Objects.equals(priority, that.priority) &&
Objects.equals(selector, that.selector) &&
Objects.equals(tableId, that.tableId);
}
return false;
}
@Override
public String toString() {
return toStringHelper(this)
.add("id", Long.toHexString(id.value()))
.add("deviceId", deviceId)
.add("priority", priority)
.add("selector", selector.criteria())
.add("treatment", treatment == null ? "N/A" : treatment.allInstructions())
.add("tableId", tableId)
.add("created", created)
.toString();
}
@Override
public int timeout() {
return timeout;
}
@Override
public boolean isPermanent() {
return permanent;
}
@Override
public int tableId() {
return tableId;
}
public static Builder builder() {
return new Builder();
}
public static final class Builder implements FlowRule.Builder {
private FlowId flowId;
private Integer priority;
private DeviceId deviceId;
private Integer tableId = 0;
private TrafficSelector selector;
private TrafficTreatment treatment;
private Integer timeout;
private Boolean permanent;
@Override
public FlowRule.Builder withCookie(long cookie) {
this.flowId = FlowId.valueOf(cookie);
return this;
}
@Override
public FlowRule.Builder fromApp(ApplicationId appId) {
this.flowId = computeFlowId(appId);
return this;
}
@Override
public FlowRule.Builder withPriority(int priority) {
this.priority = priority;
return this;
}
@Override
public FlowRule.Builder forDevice(DeviceId deviceId) {
this.deviceId = deviceId;
return this;
}
@Override
public FlowRule.Builder forTable(int tableId) {
this.tableId = tableId;
return this;
}
@Override
public FlowRule.Builder withSelector(TrafficSelector selector) {
this.selector = selector;
return this;
}
@Override
public FlowRule.Builder withTreatment(TrafficTreatment treatment) {
this.treatment = treatment;
return this;
}
@Override
public FlowRule.Builder makePermanent() {
this.timeout = 0;
this.permanent = true;
return this;
}
@Override
public FlowRule.Builder makeTemporary(int timeout) {
this.permanent = false;
this.timeout = timeout;
return this;
}
@Override
public FlowRule build() {
checkNotNull(flowId != null, "Either an application" +
" id or a cookie must be supplied");
checkNotNull(selector != null, "Traffic selector cannot be null");
checkNotNull(timeout != null || permanent != null, "Must either have " +
"a timeout or be permanent");
checkNotNull(deviceId != null, "Must refer to a device");
checkNotNull(priority != null, "Priority cannot be null");
checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
MIN_PRIORITY);
return new DefaultFlowRule(deviceId, selector, treatment, priority,
flowId, permanent, timeout, tableId);
}
private FlowId computeFlowId(ApplicationId appId) {
return FlowId.valueOf((((long) appId.id()) << 48)
| (hash() & 0xffffffffL));
}
private int hash() {
return Objects.hash(deviceId, selector, treatment, tableId);
}
}
}