[ONOS-7003] Policer implementation

Changes:
- Introduce trafficcontrol package
- Add policer
- Add policer id
- Add policing resource
- Add token bucket
- Add unit tests

Change-Id: I70065d58d3df7033e67a81943ebf60187c33c3e2
This commit is contained in:
Pier Luigi 2017-09-14 22:00:30 +02:00 committed by Andrea Campanella
parent 8b3a5f6751
commit 09220c20d7
14 changed files with 1938 additions and 0 deletions

View File

@ -0,0 +1,260 @@
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.behaviour.trafficcontrol;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
import java.util.Collection;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Default implementation of the policer interface.
*/
@Beta
public final class DefaultPolicer implements Policer, PolicerEntry {
// Immutable parameters
private final DeviceId deviceId;
private final ApplicationId applicationId;
private final PolicerId policerId;
private final boolean colorAware;
private final Unit unit;
private final Collection<TokenBucket> tokenBuckets;
private final String description;
// Mutable parameters
private long referenceCount;
private long processedPackets;
private long processedBytes;
private long life;
private DefaultPolicer(DeviceId dId, ApplicationId aId, PolicerId pId,
boolean cA, Unit u, Collection<TokenBucket> tB,
String d) {
deviceId = dId;
applicationId = aId;
policerId = pId;
colorAware = cA;
unit = u;
tokenBuckets = tB;
description = d;
}
@Override
public DeviceId deviceId() {
return deviceId;
}
@Override
public ApplicationId applicationId() {
return applicationId;
}
@Override
public PolicerId policerId() {
return policerId;
}
@Override
public boolean isColorAware() {
return colorAware;
}
@Override
public Unit unit() {
return unit;
}
@Override
public Collection<TokenBucket> tokenBuckets() {
return tokenBuckets;
}
@Override
public String description() {
return description;
}
@Override
public long referenceCount() {
return referenceCount;
}
@Override
public void setReferenceCount(long count) {
referenceCount = count;
}
@Override
public long processedPackets() {
return processedPackets;
}
@Override
public void setProcessedPackets(long packets) {
processedPackets = packets;
}
@Override
public long processedBytes() {
return processedBytes;
}
@Override
public void setProcessedBytes(long bytes) {
processedBytes = bytes;
}
@Override
public long life() {
return life;
}
@Override
public void setLife(long l) {
life = l;
}
@Override
public String toString() {
return toStringHelper(this)
.add("appId", applicationId())
.add("id", policerId())
.add("isColorAware", isColorAware())
.add("unit", unit())
.add("tokenBuckets", tokenBuckets())
.add("description", description())
.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
DefaultPolicer that = (DefaultPolicer) o;
return Objects.equal(policerId, that.policerId);
}
@Override
public int hashCode() {
return policerId.hashCode();
}
/**
* Returns a new builder reference.
*
* @return a new builder
*/
public static Builder builder() {
return new Builder();
}
/**
* Implementation of the policer builder interface.
*/
public static final class Builder implements Policer.Builder {
private DeviceId deviceId;
private ApplicationId applicationId;
private PolicerId policerId;
// Default to unaware
private boolean colorAware = false;
// Default to MBps
private Unit unit = Unit.MB_PER_SEC;
private Collection<TokenBucket> tokenBuckets;
private String description = "";
@Override
public Policer.Builder forDeviceId(DeviceId dId) {
deviceId = dId;
return this;
}
@Override
public Policer.Builder fromApp(ApplicationId appId) {
applicationId = appId;
return this;
}
@Override
public Policer.Builder withId(PolicerId id) {
policerId = id;
return this;
}
@Override
public Policer.Builder colorAware(boolean isColorAware) {
colorAware = isColorAware;
return this;
}
@Override
public Policer.Builder withUnit(Unit u) {
unit = u;
return this;
}
@Override
public Policer.Builder withPolicingResource(PolicingResource policingResource) {
policerId = policingResource.policerId();
deviceId = policingResource.connectPoint().deviceId();
return this;
}
@Override
public Policer.Builder withTokenBuckets(Collection<TokenBucket> tB) {
tokenBuckets = ImmutableSet.copyOf(tB);
return this;
}
@Override
public Policer.Builder withDescription(String d) {
description = d;
return this;
}
@Override
public DefaultPolicer build() {
// Not null condition on some mandatory parameters
checkNotNull(deviceId, "Must specify a deviceId");
checkNotNull(applicationId, "Must specify an application id");
checkNotNull(policerId, "Must specify a policer id");
checkNotNull(unit, "Must specify a unit for the policer");
checkNotNull(tokenBuckets, "Must have token buckets");
checkNotNull(description, "Must have a description");
// Verify argument conditions
checkArgument(!tokenBuckets.isEmpty(), "Must have at least one token bucket");
// Finally we build the policer
return new DefaultPolicer(deviceId, applicationId, policerId,
colorAware, unit, tokenBuckets,
description);
}
}
}

View File

@ -0,0 +1,179 @@
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.behaviour.trafficcontrol;
import com.google.common.annotations.Beta;
import com.google.common.base.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;
import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DSCP_CLASS;
import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DSCP_PRECEDENCE;
/**
* Default implementation of the token bucket interface.
*/
@Beta
public final class DefaultTokenBucket implements TokenBucket, TokenBucketEntry {
// Immutable parameters
private final long rate;
private final long burstSize;
private final Action action;
private final short dscp;
// Mutable parameters
private long processedPackets;
private long processedBytes;
private DefaultTokenBucket(long r, long bS, Action a, short d) {
rate = r;
burstSize = bS;
action = a;
dscp = d;
}
@Override
public long rate() {
return rate;
}
@Override
public long burstSize() {
return burstSize;
}
@Override
public Action action() {
return action;
}
@Override
public short dscp() {
return dscp;
}
@Override
public long processedPackets() {
return processedPackets;
}
@Override
public void setProcessedPackets(long packets) {
processedPackets = packets;
}
@Override
public long processedBytes() {
return processedBytes;
}
@Override
public void setProcessedBytes(long bytes) {
processedBytes = bytes;
}
@Override
public String toString() {
return toStringHelper(this)
.add("rate", rate())
.add("burstSize", burstSize())
.add("action", action())
.add("dscp", dscp()).toString();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
DefaultTokenBucket that = (DefaultTokenBucket) o;
return rate == that.rate &&
burstSize == that.burstSize &&
Objects.equal(action, that.action) &&
dscp == that.dscp;
}
@Override
public int hashCode() {
return Objects.hashCode(rate, burstSize, action, dscp);
}
/**
* Returns a new builder reference.
*
* @return a new builder
*/
public static Builder builder() {
return new Builder();
}
/**
* Implementation of the token bucket builder interface.
*/
public static final class Builder implements TokenBucket.Builder {
private long rate;
// Default to 2 * MTU
private long burstSize = 2 * 1500;
private Action action;
private short dscp;
@Override
public TokenBucket.Builder withRate(long r) {
rate = r;
return this;
}
@Override
public TokenBucket.Builder withBurstSize(long bS) {
burstSize = bS;
return this;
}
@Override
public TokenBucket.Builder withAction(Action a) {
action = a;
return this;
}
@Override
public TokenBucket.Builder withDscp(short d) {
dscp = d;
return this;
}
@Override
public DefaultTokenBucket build() {
// Not null condition on the action
checkNotNull(action, "Must specify an action");
// If action is based on DSCP modification
if (action == DSCP_CLASS || action == DSCP_PRECEDENCE) {
// dscp should be a value between 0 and 255
checkArgument(dscp >= MIN_DSCP && dscp <= MAX_DSCP, "Dscp is out of range");
}
// Finally we build the token bucket
return new DefaultTokenBucket(rate, burstSize, action, dscp);
}
}
}

View File

@ -0,0 +1,262 @@
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.behaviour.trafficcontrol;
import com.google.common.annotations.Beta;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
import java.util.Collection;
/**
* Generic abstraction for a policer which can mark and/or discard ingress
* traffic. Each policer is made up of an identifier and a set of attributes
* which defines the type of policer.
* <p>
* For example a policer specifying only a single token bucket, it will model
* a simple drop policer or a marker policer. For the former, the traffic in
* profile is green or red if it is out-of-profile. The latter envisages green
* or yellow traffic. Currently there is no RFC for this kind of policer but
* some vendors implement this model.
* <p>
* RFC 2697 can be modelled creating a policer with a collection of two
* token buckets: [0] CIR + CBS; [1] CIR + EBS. In this way, it is possible
* to create a policer single rate three color marker.
* <p>
* RFC 2698 and P4 meter are modelled in the same way but different attributes
* for the token buckets: [0] PIR + PBS; [2] CIR + CBS. In this way, we can
* create a policer two rate three color marker.
* <p>
* How these policers will be implemented depends on the specific technology
* used in the device. For an OF device, the single rate two color marker it
* could be implemented with a simple meter with a drop band.
* <p>
* Following abstraction has been designed to cover several types of policing
* that have been specified during the years. However, this does not assure that
* used technology will support all possible scenarios. For example, OF limitations
* are well known in this field and implementations are even worse.
*/
@Beta
public interface Policer {
/**
* Unit of traffic used by this policer.
*/
enum Unit {
/**
* Packets per second.
*/
PKTS_PER_SEC,
/**
* Byte per second.
*/
B_PER_SEC,
/**
* KByte per second.
*/
KB_PER_SEC,
/**
* MByte per second.
*/
MB_PER_SEC
}
/**
* The device of this policer, where policing
* is applied.
*
* @return the device id
*/
DeviceId deviceId();
/**
* The id of the application which created this policer.
*
* @return the identifier of the application
*/
ApplicationId applicationId();
/**
* Returns how many are referencing this policer.
*
* Availability of this information depends on the
* technology used for the implementation of this policer.
*
* @return the reference count
*/
long referenceCount();
/**
* Stats which reports how many packets have been
* processed so far.
*
* Availability of this information depends on the
* technology used for the implementation of this policer.
*
* @return the processed packets
*/
long processedPackets();
/**
* Stats which reports how many bytes have been
* processed so far.
*
* Availability of this information depends on the
* technology used for the implementation of this policer.
*
* @return the processed bytes
*/
long processedBytes();
/**
* The id of this policer.
*
* @return the policer id
*/
PolicerId policerId();
/**
* Indicates if this policer is aware of the marking indication
* in the ethernet frames.
*
* TODO Understand for the future how it is implemented by the vendors
*
* @return true if this policer is color aware.
*/
boolean isColorAware();
/**
* The lifetime in seconds of this policer.
*
* Availability of this information depends on the
* technology used for the implementation of this policer.
*
* @return number of seconds
*/
long life();
/**
* The unit used within this policer.
*
* @return the unit
*/
Unit unit();
/**
* The token buckets used within this policer.
*
* @return the list of the token buckets
*/
Collection<TokenBucket> tokenBuckets();
/**
* Brief description of this policer.
*
* @return human readable description
*/
String description();
/**
* A policer builder.
*/
interface Builder {
/**
* Assigns the device for this policer.
* <p>
* Note: mandatory setter for this builder
* </p>
* @param deviceId a device id
* @return this
*/
Builder forDeviceId(DeviceId deviceId);
/**
* Assigns the application that built this policer.
* <p>
* Note: mandatory setter for this builder
* </p>
* @param appId an application id
* @return this
*/
Builder fromApp(ApplicationId appId);
/**
* Assigns the id to this policer.
* <p>
* Note: mandatory setter for this builder
* </p>
* @param id an identifier
* @return this
*/
Builder withId(PolicerId id);
/**
* Sets this policer to be color aware.
* Defaults to false.
*
* @param isColorAware if it is color aware or not
* @return this
*/
Builder colorAware(boolean isColorAware);
/**
* Assigns the unit to use for this policer.
* Defaults to MB/s.
*
* @param unit a unit
* @return this
*/
Builder withUnit(Unit unit);
/**
* Assigns policer id and device id for this policer.
*
* @param policingResource the policing resource
* @return this
*/
Builder withPolicingResource(PolicingResource policingResource);
/**
* Assigns token buckets for this policer.
* <p>
* Note: at least one token bucket
* </p>
* @param tokenBuckets the collection of token buckets
* @return this
*/
Builder withTokenBuckets(Collection<TokenBucket> tokenBuckets);
/**
* Assigns description for this policer.
* Default is empty description.
*
* @param description the description
* @return this
*/
Builder withDescription(String description);
/**
* Builds the policer based on the specified parameters
* when possible.
*
* @return a policer
*/
Policer build();
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.behaviour.trafficcontrol;
import com.google.common.annotations.Beta;
/**
* Represents a stored policer.
*/
@Beta
public interface PolicerEntry {
/**
* Set the amount of time the policer has existed in seconds.
*
* @param life number of seconds
*/
void setLife(long life);
/**
* Sets how many are using this policer.
*
* @param count a reference count.
*/
void setReferenceCount(long count);
/**
* Updates the number of packets seen by this policer.
*
* @param packets a packet count.
*/
void setProcessedPackets(long packets);
/**
* Updates the number of bytes seen by the policer.
*
* @param bytes a byte counter.
*/
void setProcessedBytes(long bytes);
}

View File

@ -0,0 +1,88 @@
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.behaviour.trafficcontrol;
import com.google.common.annotations.Beta;
import org.onlab.util.Identifier;
import java.net.URI;
import static com.google.common.base.Preconditions.checkArgument;
/**
* Unique identifier for an ONOS Policer {@link org.onosproject.net.behaviour.trafficcontrol.Policer}.
* It uniquely identifies a Policer in the scope of a single device inside ONOS. There may not be any
* correspondence with the identifiers of the technology implementing the Policer in the device.
* Mapping (if necessary) is left to the specific implementation.
*/
@Beta
public final class PolicerId extends Identifier<String> {
/**
* Represents either no id, or an unspecified id.
*/
public static final PolicerId NONE = policerId("none:none");
private static final int POLICER_ID_MAX_LENGTH = 1024;
private final URI uri;
// Not allowed
private PolicerId(URI u) {
super(u.toString());
uri = u;
}
// Needed for serialization
private PolicerId() {
super();
uri = null;
}
/**
* Creates a policer id using the supplied URI.
*
* @param uri policer id URI
* @return PolicerId
*/
public static PolicerId policerId(URI uri) {
return new PolicerId(uri);
}
/**
* Creates a policer id using the supplied URI string.
*
* @param string policer id URI string
* @return PolicerID
*/
public static PolicerId policerId(String string) {
checkArgument(string.length() <= POLICER_ID_MAX_LENGTH,
"URI string exceeds maximum length " + POLICER_ID_MAX_LENGTH);
return policerId(URI.create(string));
}
/**
* Returns the backing URI.
*
* @return backing URI
*/
public URI uri() {
return uri;
}
}

View File

@ -0,0 +1,89 @@
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.behaviour.trafficcontrol;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.NetworkResource;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Abstraction which encapsulates policer
* data to be used as network resource.
*/
@Beta
public final class PolicingResource implements NetworkResource {
// The policer id identifying this resource
private final PolicerId policerId;
// The connect point where the policer applies
private final ConnectPoint connectPoint;
public PolicingResource(PolicerId pId, ConnectPoint cP) {
checkNotNull(pId, "Must specify a policer id");
checkNotNull(cP, "Must specify a connect point");
policerId = pId;
connectPoint = cP;
}
/**
* Return the policer id of this resource.
*
* @return the policer id
*/
public PolicerId policerId() {
return policerId;
}
/**
* Returns the connect point of this resource.
*
* @return the connect point
*/
public ConnectPoint connectPoint() {
return connectPoint;
}
@Override
public String toString() {
return toStringHelper(this)
.add("id", policerId())
.add("connectPoint", connectPoint()).toString();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
PolicingResource that = (PolicingResource) o;
return Objects.equal(policerId, that.policerId) &&
Objects.equal(connectPoint, that.connectPoint);
}
@Override
public int hashCode() {
return Objects.hashCode(policerId, connectPoint);
}
}

View File

@ -0,0 +1,163 @@
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.behaviour.trafficcontrol;
import com.google.common.annotations.Beta;
/**
* Generic abstraction for a token bucket which can mark and/or discard
* traffic. Each token bucket in ONOS is made up of a set of attributes which
* identifies the type.
*/
@Beta
public interface TokenBucket {
/**
* Upper bound for DSCP.
*/
short MAX_DSCP = 255;
/**
* Lower bound for DSCP.
*/
short MIN_DSCP = 0;
/**
* Action applied to the exceeding traffic.
* Action depends on the tocken bucket type
*/
enum Action {
/**
* Drop action.
*/
DROP,
/**
* Marking increases DSCP drop precedence.
*/
DSCP_PRECEDENCE,
/**
* Marking sets DSCP class.
*/
DSCP_CLASS,
/**
* Marking sets Drop Elegible Indicator.
*/
DEI
}
/**
* Rate of traffic subject to the SLAs
* specified for this token bucket.
*
* @return the rate value
*/
long rate();
/**
* Maximum burst size subject to the SLAs
* specified for this token bucket.
*
* @return the burst size in bytes
*/
long burstSize();
/**
* Action used by this token bucket
* for the exceeding traffic.
*
* @return the type of action
*/
Action action();
/**
* Dscp value, it meaning depends on the used marking.
*
* @return the dscp value for this token bucket
*/
short dscp();
/**
* Stats which reports how many packets have been
* processed so far.
*
* Availability of this information depends on the
* technology used for the implementation of the policer.
*
* @return the processed packets
*/
long processedPackets();
/**
* Stats which reports how many bytes have been
* processed so far.
*
* Availability of this information depends on the
* technology used for the implementation of the policer.
*
* @return the processed bytes
*/
long processedBytes();
/**
* Token bucket builder.
*/
interface Builder {
/**
* Assigns the rate to this token bucket.
*
* @param rate a rate value
* @return this
*/
Builder withRate(long rate);
/**
* Assigns the burst size to this token bucket.
* Default to 2 * 1500 bytes.
*
* @param burstSize a burst size
* @return this
*/
Builder withBurstSize(long burstSize);
/**
* Assigns the action to this token bucket.
* <p>
* Note: mandatory setter for this builder
* </p>
* @param action an action
* @return this
*/
Builder withAction(Action action);
/**
* Assigns the dscp value to this token bucket.
*
* @param dscp a dscp value
* @return this
*/
Builder withDscp(short dscp);
/**
* Builds the token bucket based on the specified
* parameters when possible.
*
* @return a token bucket
*/
TokenBucket build();
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.behaviour.trafficcontrol;
import com.google.common.annotations.Beta;
/**
* Represents a stored token bucket.
*/
@Beta
public interface TokenBucketEntry {
/**
* Updates the number of packets seen by this token bucket.
*
* @param packets a packet count.
*/
void setProcessedPackets(long packets);
/**
* Updates the number of bytes seen by this token bucket.
*
* @param bytes a byte counter.
*/
void setProcessedBytes(long bytes);
}

View File

@ -0,0 +1,20 @@
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.
*/
/**
* Traffic control behaviors and related classes.
*/
package org.onosproject.net.behaviour.trafficcontrol;

View File

@ -0,0 +1,139 @@
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.behaviour.trafficcontrol;
import com.google.common.base.Strings;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.onlab.junit.ImmutableClassChecker;
import java.net.URI;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
/**
* Test class for PolicerId.
*/
public class PolicerIdTest {
// Test scheme
private static final String FOO_SCHEME = "foo";
// OpenFlow scheme
private static final String OF_SCHEME = "of";
// Some test ids
private static final Short ONE = 1;
private static final Short TWO = 15;
private static final String A = "A";
private static final String LA = "a";
/**
* Test policer id creation from URI.
*/
@Test
public void testfromUriCreation() {
// Create URI representing the id
URI uriOne = URI.create(OF_SCHEME + ":" + Integer.toHexString(ONE));
// Create policer id
PolicerId one = PolicerId.policerId(uriOne);
// Verify proper creation
assertThat(one, notNullValue());
assertThat(one.id(), is(uriOne.toString().toLowerCase()));
assertThat(one.uri(), is(uriOne));
}
/**
* Test policer id creation from string.
*/
@Test
public void testfromStringCreation() {
// Create String representing the id
String stringTwo = OF_SCHEME + ":" + Integer.toHexString(TWO);
// Create policer id
PolicerId two = PolicerId.policerId(stringTwo);
// Verify proper creation
assertThat(two, notNullValue());
assertThat(two.id(), is(stringTwo));
assertThat(two.uri(), is(URI.create(stringTwo)));
}
/**
* Exception expected to raise when creating a wrong policer id.
*/
@Rule
public ExpectedException exceptionWrongId = ExpectedException.none();
/**
* Test wrong creation of a policer id.
*/
@Test
public void testWrongCreation() {
// Build not allowed string
String wrongString = Strings.repeat("x", 1025);
// Define expected exception
exceptionWrongId.expect(IllegalArgumentException.class);
// Create policer id
PolicerId.policerId(wrongString);
}
/**
* Test equality between policer ids.
*/
@Test
public void testEquality() {
// Create URI representing the id one
URI uriOne = URI.create(OF_SCHEME + ":" + Integer.toHexString(ONE));
// Create String representing the id one
String stringOne = OF_SCHEME + ":" + Integer.toHexString(ONE);
// Create String representing the id two
String stringTwo = OF_SCHEME + ":" + Integer.toHexString(TWO);
// Create String representing the id A
String stringA = FOO_SCHEME + ":" + A;
// Create String representing the id LA
String stringLA = FOO_SCHEME + ":" + LA;
// Create policer id one
PolicerId one = PolicerId.policerId(uriOne);
// Create policer id one
PolicerId copyOfOne = PolicerId.policerId(stringOne);
// Verify equality
assertEquals(one, copyOfOne);
// Create a different policer id
PolicerId two = PolicerId.policerId(stringTwo);
// Verify not equals
assertNotEquals(two, one);
assertNotEquals(two, copyOfOne);
// Create policer id A
PolicerId a = PolicerId.policerId(A);
// Create policer id LA
PolicerId la = PolicerId.policerId(LA);
// Verify not equals
assertNotEquals(a, la);
}
/**
* Tests immutability of PolicerId.
*/
@Test
public void testImmutability() {
ImmutableClassChecker.assertThatClassIsImmutable(PolicerId.class);
}
}

View File

@ -0,0 +1,343 @@
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.behaviour.trafficcontrol;
import com.google.common.collect.ImmutableList;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.onosproject.TestApplicationId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*;
import static org.onosproject.net.behaviour.trafficcontrol.Policer.Unit.KB_PER_SEC;
import static org.onosproject.net.behaviour.trafficcontrol.Policer.Unit.MB_PER_SEC;
import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DROP;
import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DSCP_CLASS;
import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DSCP_PRECEDENCE;
/**
* Test class for policer implementation.
*/
public class PolicerTest {
// Fake Application Id
private static final ApplicationId FOO_APP_ID = new TestApplicationId("foo");
// Connect points
private static final String SDID1 = "of:00000000000001";
private static final DeviceId DID1 = DeviceId.deviceId(SDID1);
// OpenFlow scheme
private static final String OF_SCHEME = "of";
// Policers identifiers
private static final String SID1 = OF_SCHEME + ":" + Integer.toHexString(1);
private static final PolicerId ID1 = PolicerId.policerId(SID1);
private static final String SID2 = OF_SCHEME + ":" + Integer.toHexString(2);
private static final PolicerId ID2 = PolicerId.policerId(SID2);
private static final String SID3 = OF_SCHEME + ":" + Integer.toHexString(3);
private static final PolicerId ID3 = PolicerId.policerId(SID3);
private static final String SID4 = OF_SCHEME + ":" + Integer.toHexString(4);
private static final PolicerId ID4 = PolicerId.policerId(SID4);
private static final String SID5 = OF_SCHEME + ":" + Integer.toHexString(5);
private static final PolicerId ID5 = PolicerId.policerId(SID5);
private static final String SID6 = OF_SCHEME + ":" + Integer.toHexString(6);
private static final PolicerId ID6 = PolicerId.policerId(SID6);
private static final String SID7 = OF_SCHEME + ":" + Integer.toHexString(7);
private static final PolicerId ID7 = PolicerId.policerId(SID7);
private static final String SID8 = OF_SCHEME + ":" + Integer.toHexString(8);
private static final PolicerId ID8 = PolicerId.policerId(SID8);
private static final String SID9 = OF_SCHEME + ":" + Integer.toHexString(9);
private static final PolicerId ID9 = PolicerId.policerId(SID9);
/**
* Test block traffic policer.
*/
@Test
public void testBlockCreation() {
// Create a block traffic token bucket
TokenBucket tokenBucket = DefaultTokenBucket.builder()
.withBurstSize(0)
.withAction(DROP)
.build();
// Create a policer with above token bucket
Policer policer = DefaultPolicer.builder()
.forDeviceId(DID1)
.fromApp(FOO_APP_ID)
.withId(ID1)
.withTokenBuckets(ImmutableList.of(tokenBucket))
.build();
// Assert on device id
assertThat(policer.deviceId(), is(DID1));
// Assert on app id
assertThat(policer.applicationId(), is(FOO_APP_ID));
// Assert on policer id
assertThat(policer.policerId(), is(ID1));
// It is not color aware
assertFalse(policer.isColorAware());
// Unit is Mbps
assertThat(policer.unit(), is(MB_PER_SEC));
// One token bucket
assertThat(policer.tokenBuckets().size(), is(1));
// One token bucket equals to tokenBucket
assertTrue(policer.tokenBuckets().contains(tokenBucket));
}
/**
* Test simple drop policer.
*/
@Test
public void testDropCreation() {
// Create a drop traffic token bucket at 1MB/s
TokenBucket tokenBucket = DefaultTokenBucket.builder()
.withRate(1)
.withAction(DROP)
.build();
// Create a policer with above token bucket
Policer policer = DefaultPolicer.builder()
.forDeviceId(DID1)
.fromApp(FOO_APP_ID)
.withId(ID2)
.withTokenBuckets(ImmutableList.of(tokenBucket))
.build();
// Assert on device id
assertThat(policer.deviceId(), is(DID1));
// Assert on app id
assertThat(policer.applicationId(), is(FOO_APP_ID));
// Assert on policer id
assertThat(policer.policerId(), is(ID2));
// It is not color aware
assertFalse(policer.isColorAware());
// Unit is Mbps
assertThat(policer.unit(), is(MB_PER_SEC));
// One token bucket
assertThat(policer.tokenBuckets().size(), is(1));
// One token bucket equals to tokenBucket
assertTrue(policer.tokenBuckets().contains(tokenBucket));
}
/**
* Test simple mark policer.
*/
@Test
public void testMarkCreation() {
// Create a drop traffic token bucket at 1MB/s
TokenBucket tokenBucket = DefaultTokenBucket.builder()
.withRate(1)
.withAction(DSCP_PRECEDENCE)
.withDscp((short) 2)
.build();
// Create a policer with above token bucket
Policer policer = DefaultPolicer.builder()
.forDeviceId(DID1)
.fromApp(FOO_APP_ID)
.withId(ID3)
.withTokenBuckets(ImmutableList.of(tokenBucket))
.build();
// Assert on device id
assertThat(policer.deviceId(), is(DID1));
// Assert on app id
assertThat(policer.applicationId(), is(FOO_APP_ID));
// Assert on policer id
assertThat(policer.policerId(), is(ID3));
// It is not color aware
assertFalse(policer.isColorAware());
// Unit is Mbps
assertThat(policer.unit(), is(MB_PER_SEC));
// One token bucket
assertThat(policer.tokenBuckets().size(), is(1));
// One token bucket equals to tokenBucket
assertTrue(policer.tokenBuckets().contains(tokenBucket));
}
/**
* Test single rate three colors scenario (RFC 2697).
*/
@Test
public void testSingleRateThreeColors() {
// Create token bucket for committed rate
TokenBucket crTokenBucket = DefaultTokenBucket.builder()
.withRate(1)
.withAction(DSCP_PRECEDENCE)
.withDscp((short) 2)
.build();
// Create token bucket for excess rate
TokenBucket erTokenBucket = DefaultTokenBucket.builder()
.withRate(1)
.withBurstSize(4 * 1500)
.withAction(DROP)
.build();
// Create a policer with above token buckets
Policer policer = DefaultPolicer.builder()
.forDeviceId(DID1)
.fromApp(FOO_APP_ID)
.withId(ID4)
// The order is important
.withTokenBuckets(ImmutableList.of(crTokenBucket, erTokenBucket))
.build();
// Assert on device id
assertThat(policer.deviceId(), is(DID1));
// Assert on app id
assertThat(policer.applicationId(), is(FOO_APP_ID));
// Assert on policer id
assertThat(policer.policerId(), is(ID4));
// It is not color aware
assertFalse(policer.isColorAware());
// Unit is Mbps
assertThat(policer.unit(), is(MB_PER_SEC));
// Two token buckets
assertThat(policer.tokenBuckets().size(), is(2));
// One token bucket equals to crTokenBucket
assertTrue(policer.tokenBuckets().contains(crTokenBucket));
// One token bucket equals to erTokenBucket
assertTrue(policer.tokenBuckets().contains(erTokenBucket));
}
/**
* Test two rates three colors scenario (RFC 2698 and P4 meter).
*/
@Test
public void testTwoRatesThreeColors() {
// Create token bucket for peak rate at 10Mb/s
TokenBucket prTokenBucket = DefaultTokenBucket.builder()
// (10 * 1000)/8 ---> 1250KB/s
.withRate(1250)
.withBurstSize(10 * 1500)
.withAction(DROP)
.build();
// Create token bucket for committed rate at 1Mb/s
TokenBucket crTokenBucket = DefaultTokenBucket.builder()
// (1 * 1000)/8 ---> 125KB/s
.withRate(125)
.withAction(DSCP_CLASS)
.withDscp((short) 10)
.build();
// Create a policer with above token buckets
Policer policer = DefaultPolicer.builder()
.forDeviceId(DID1)
.fromApp(FOO_APP_ID)
.withId(ID5)
.withUnit(KB_PER_SEC)
// The order is important
.withTokenBuckets(ImmutableList.of(prTokenBucket, crTokenBucket))
.build();
// Assert on device id
assertThat(policer.deviceId(), is(DID1));
// Assert on app id
assertThat(policer.applicationId(), is(FOO_APP_ID));
// Assert on policer id
assertThat(policer.policerId(), is(ID5));
// It is not color aware
assertFalse(policer.isColorAware());
// Unit is Mbps
assertThat(policer.unit(), is(KB_PER_SEC));
// Two token buckets
assertThat(policer.tokenBuckets().size(), is(2));
// One token bucket equals to prTokenBucket
assertTrue(policer.tokenBuckets().contains(prTokenBucket));
// One token bucket equals to crTokenBucket
assertTrue(policer.tokenBuckets().contains(crTokenBucket));
}
/**
* Exception expected to raise when creating a policer with null params.
*/
@Rule
public ExpectedException exceptionNullParam = ExpectedException.none();
/**
* Test creation with null parameters.
*/
@Test
public void testNullParam() {
// Define expected exception
exceptionNullParam.expect(NullPointerException.class);
// Invalid policer, device id is not defined
DefaultPolicer.builder()
.fromApp(FOO_APP_ID)
.withId(ID6)
.build();
}
/**
* Exception expected to raise when creating a policer without token buckets.
*/
@Rule
public ExpectedException exceptionNoTokenBuckets = ExpectedException.none();
/**
* Test creation without token buckets.
*/
@Test
public void testNoTokenBuckets() {
// Define expected exception
exceptionNoTokenBuckets.expect(IllegalArgumentException.class);
// Invalid policer, no token buckets
DefaultPolicer.builder()
.fromApp(FOO_APP_ID)
.withId(ID7)
.forDeviceId(DID1)
.withTokenBuckets(ImmutableList.of())
.build();
}
/**
* Test equality between policers.
*/
@Test
public void testEqualilty() {
// Create a block traffic token bucket
TokenBucket blockTokenBucket = DefaultTokenBucket.builder()
.withBurstSize(0)
.withAction(DROP)
.build();
// Create a mark traffic token bucket
TokenBucket markTokenBucket = DefaultTokenBucket.builder()
.withBurstSize(0)
.withAction(DSCP_CLASS)
.withDscp((short) 10)
.build();
// Create first policer
Policer policerOne = DefaultPolicer.builder()
.forDeviceId(DID1)
.fromApp(FOO_APP_ID)
.withId(ID8)
.withTokenBuckets(ImmutableList.of(blockTokenBucket))
.build();
// Create second policer
Policer policerTwo = DefaultPolicer.builder()
.forDeviceId(DID1)
.fromApp(FOO_APP_ID)
.withId(ID9)
.withTokenBuckets(ImmutableList.of(markTokenBucket))
.build();
// Create third policer copy of one
// Create first policer
Policer policerThree = DefaultPolicer.builder()
.forDeviceId(DID1)
.fromApp(FOO_APP_ID)
.withId(ID8)
.withTokenBuckets(ImmutableList.of(blockTokenBucket))
.build();
// One and Three are equal
assertEquals(policerOne, policerThree);
// Two is different due to the different id
assertNotEquals(policerOne, policerTwo);
assertNotEquals(policerThree, policerTwo);
}
}

View File

@ -0,0 +1,100 @@
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.behaviour.trafficcontrol;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.onlab.junit.ImmutableClassChecker;
import org.onosproject.net.ConnectPoint;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.*;
/**
* Test class for PolicingResource.
*/
public class PolicingResourceTest {
// Connectpoints
private static final String SCP1 = "of:00000000000001/1";
private static final String SCP2 = "of:00000000000001/2";
private static final ConnectPoint CP1 = ConnectPoint.deviceConnectPoint(SCP1);
private static final ConnectPoint CP2 = ConnectPoint.deviceConnectPoint(SCP2);
// OpenFlow scheme
private static final String OF_SCHEME = "of";
// Policer identifier
private static final String SID = OF_SCHEME + ":" + Integer.toHexString(1);
private static final PolicerId PID = PolicerId.policerId(SID);
/**
* Test policing resource creation.
*/
@Test
public void testCreation() {
// Create a new policing resource
PolicingResource policingResource = new PolicingResource(PID, CP1);
// Verify proper creation
assertThat(policingResource, notNullValue());
assertThat(policingResource.policerId(), is(PID));
assertThat(policingResource.connectPoint(), is(CP1));
}
/**
* Exception expected to raise when creating policing resource with null id.
*/
@Rule
public ExpectedException exceptionNullId = ExpectedException.none();
/**
* Test wrong creation of a policing resource.
*/
@Test
public void testNullIdCreation() {
// Define expected exception
exceptionNullId.expect(NullPointerException.class);
// Create wrong policing resource
new PolicingResource(null, CP1);
}
/**
* Test equality between policing resources.
*/
@Test
public void testEqualilty() {
// Create two identical resources
PolicingResource one = new PolicingResource(PID, CP1);
PolicingResource copyOfOne = new PolicingResource(PID, CP1);
// Verify equality
assertEquals(one, copyOfOne);
// Create a different resource
PolicingResource two = new PolicingResource(PID, CP2);
// Verify not equals
assertNotEquals(two, one);
assertNotEquals(two, copyOfOne);
}
/**
* Tests immutability of PolicingResource.
*/
@Test
public void testImmutability() {
ImmutableClassChecker.assertThatClassIsImmutable(PolicingResource.class);
}
}

View File

@ -0,0 +1,179 @@
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.behaviour.trafficcontrol;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.*;
import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DROP;
import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DSCP_CLASS;
import static org.onosproject.net.behaviour.trafficcontrol.TokenBucket.Action.DSCP_PRECEDENCE;
/**
* Test class for TokenBucket.
*/
public class TokenBucketTest {
// Test rate
private static final long RATE = 1;
// Test dscp drop precedence
private static final short DSCP_PREC = 2;
// Test dscp class
private static final short DSCP_CL = 250;
// Test wrong dscp
private static final short WRONG_DSCP = -1;
/**
* Test creation of a drop token bucket.
*/
@Test
public void testDropCreation() {
// Create a drop token bucket
TokenBucket drop = DefaultTokenBucket.builder()
.withRate(RATE)
.withAction(DROP)
.build();
// Not null
assertThat(drop, notNullValue());
// Rate should be equal to RATE
assertThat(drop.rate(), is(RATE));
// Burst size should be equal to 2xMTU
assertThat(drop.burstSize(), is(2 * 1500L));
// Action should be drop
assertThat(drop.action(), is(DROP));
}
/**
* Test creation of a dscp precedence token bucket.
*/
@Test
public void testDscpPrecCreation() {
// Create a dscp precedence token bucket
TokenBucket drop = DefaultTokenBucket.builder()
.withRate(RATE)
.withAction(DSCP_PRECEDENCE)
.withBurstSize(6 * 1500)
.withDscp(DSCP_PREC)
.build();
// Not null
assertThat(drop, notNullValue());
// Rate should be equal to RATE
assertThat(drop.rate(), is(RATE));
// Burst size should be equal to 6xMTU
assertThat(drop.burstSize(), is(6 * 1500L));
// Action should increase dscp drop precedence
assertThat(drop.action(), is(DSCP_PRECEDENCE));
// Dcsp drop precedence should be increased of 2
assertThat(drop.dscp(), is(DSCP_PREC));
}
/**
* Test creation of a dscp class token bucket.
*/
@Test
public void testDscpClassCreation() {
// Create a dscp class token bucket
TokenBucket drop = DefaultTokenBucket.builder()
.withRate(RATE)
.withAction(DSCP_CLASS)
.withDscp(DSCP_CL)
.build();
// Not null
assertThat(drop, notNullValue());
// Rate should be equal to RATE
assertThat(drop.rate(), is(RATE));
// Burst size should be equal to 2xMTU
assertThat(drop.burstSize(), is(2 * 1500L));
// Action should be drop
assertThat(drop.action(), is(DSCP_CLASS));
// Dcsp drop precedence should be increased of 2
assertThat(drop.dscp(), is(DSCP_CL));
}
/**
* Exception expected to raise when creating a token bucket with null action.
*/
@Rule
public ExpectedException exceptionNullAction = ExpectedException.none();
/**
* Test creation of a token bucket with null action.
*/
@Test
public void testNullActionCreation() {
// Define expected exception
exceptionNullAction.expect(NullPointerException.class);
// Create a token bucket without action
TokenBucket drop = DefaultTokenBucket.builder()
.withRate(RATE)
.build();
}
/**
* Exception expected to raise when creating a token bucket with wrong dscp.
*/
@Rule
public ExpectedException exceptionWrongDscp = ExpectedException.none();
/**
* Test creation of a token bucket with wrong dscp.
*/
@Test
public void testWrongDscpCreation() {
// Define expected exception
exceptionWrongDscp.expect(IllegalArgumentException.class);
// Create a token bucket with wrong dscp
TokenBucket drop = DefaultTokenBucket.builder()
.withRate(RATE)
.withAction(DSCP_PRECEDENCE)
.withDscp(WRONG_DSCP)
.build();
}
/**
* Test equality between policer ids.
*/
@Test
public void testEqualilty() {
// Create a drop token bucket
TokenBucket drop = DefaultTokenBucket.builder()
.withRate(RATE)
.withAction(DROP)
.build();
// Create a mark token bucket
TokenBucket mark = DefaultTokenBucket.builder()
.withRate(RATE)
.withAction(DSCP_PRECEDENCE)
.withDscp(DSCP_PREC)
.build();
// Create a copy of the drop token bucket
TokenBucket copyDrop = DefaultTokenBucket.builder()
.withRate(RATE)
.withAction(DROP)
.build();
// Verify equality
assertEquals(drop, copyDrop);
// Verify not equals
assertNotEquals(mark, drop);
assertNotEquals(mark, copyDrop);
}
}

View File

@ -0,0 +1,20 @@
/*
* Copyright 2017-present Open Networking Foundation
*
* 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.
*/
/**
* Test class for traffic control behaviors and related classes.
*/
package org.onosproject.net.behaviour.trafficcontrol;