Thiago Santos
Committed by Ray Milkey

[ONOS-4931] fix doc of FlowEntry.life(), add life(TimeUnit)

Fix the doc: life() returns the time in seconds, not milliseconds.

Add new method life(TimeUnit) that allows specifying the timeunit to
receive the life value as as seconds might not be enough for
all applications and OpenFlow can provide this value to nanoseconds resolution
(in its spec).

Change-Id: Ia6a7573797249e0edc04e03c7204a550a2823742
......@@ -16,16 +16,22 @@
package org.onosproject.net.flow;
import static com.google.common.base.MoreObjects.toStringHelper;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.slf4j.LoggerFactory.getLogger;
import org.slf4j.Logger;
import java.util.concurrent.TimeUnit;
public class DefaultFlowEntry extends DefaultFlowRule
implements StoredFlowEntry {
private static final Logger log = getLogger(DefaultFlowEntry.class);
/* Stored in nanoseconds (allows for 292 years) */
private long life;
private long packets;
private long bytes;
private FlowEntryState state;
......@@ -37,10 +43,10 @@ public class DefaultFlowEntry extends DefaultFlowRule
private final int errCode;
public DefaultFlowEntry(FlowRule rule, FlowEntryState state,
long life, long packets, long bytes) {
long life, TimeUnit lifeTimeUnit, long packets, long bytes) {
super(rule);
this.state = state;
this.life = life;
this.life = lifeTimeUnit.toNanos(life);
this.packets = packets;
this.bytes = bytes;
this.errCode = -1;
......@@ -48,15 +54,13 @@ public class DefaultFlowEntry extends DefaultFlowRule
this.lastSeen = System.currentTimeMillis();
}
public DefaultFlowEntry(FlowRule rule, FlowEntryState state,
long lifeSecs, long packets, long bytes) {
this(rule, state, lifeSecs, SECONDS, packets, bytes);
}
public DefaultFlowEntry(FlowRule rule) {
super(rule);
this.state = FlowEntryState.PENDING_ADD;
this.life = 0;
this.packets = 0;
this.bytes = 0;
this.errCode = -1;
this.errType = -1;
this.lastSeen = System.currentTimeMillis();
this(rule, FlowEntryState.PENDING_ADD, 0, 0, 0);
}
public DefaultFlowEntry(FlowRule rule, int errType, int errCode) {
......@@ -69,7 +73,12 @@ public class DefaultFlowEntry extends DefaultFlowRule
@Override
public long life() {
return life;
return life(SECONDS);
}
@Override
public long life(TimeUnit timeUnit) {
return timeUnit.convert(life, NANOSECONDS);
}
@Override
......@@ -104,7 +113,12 @@ public class DefaultFlowEntry extends DefaultFlowRule
@Override
public void setLife(long life) {
this.life = life;
setLife(life, SECONDS);
}
@Override
public void setLife(long life, TimeUnit timeUnit) {
this.life = timeUnit.toNanos(life);
}
@Override
......
......@@ -16,7 +16,10 @@
package org.onosproject.net.flow;
import java.util.concurrent.TimeUnit;
import static com.google.common.base.MoreObjects.toStringHelper;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
/**
* Default flow entry class with FlowLiveType value, IMMEDIATE_FLOW, SHORT_FLOW, MID_FLOW, LONG_FLOW.
......@@ -25,6 +28,23 @@ public class DefaultTypedFlowEntry extends DefaultFlowEntry
implements TypedStoredFlowEntry {
private FlowLiveType liveType;
/**
* Creates a typed flow entry from flow rule and its statistics, with default flow live type(IMMEDIATE_FLOW).
*
* @param rule the flow rule
* @param state the flow state
* @param life the flow duration since creation
* @param lifeTimeUnit the time unit of life
* @param packets the flow packets count
* @param bytes the flow bytes count
*/
public DefaultTypedFlowEntry(FlowRule rule, FlowEntryState state,
long life, TimeUnit lifeTimeUnit, long packets, long bytes) {
super(rule, state, life, lifeTimeUnit, packets, bytes);
this.liveType = FlowLiveType.IMMEDIATE_FLOW;
}
/**
* Creates a typed flow entry from flow rule and its statistics, with default flow live type(IMMEDIATE_FLOW).
*
......@@ -59,7 +79,7 @@ public class DefaultTypedFlowEntry extends DefaultFlowEntry
*
*/
public DefaultTypedFlowEntry(FlowEntry fe) {
super(fe, fe.state(), fe.life(), fe.packets(), fe.bytes());
super(fe, fe.state(), fe.life(NANOSECONDS), NANOSECONDS, fe.packets(), fe.bytes());
this.liveType = FlowLiveType.IMMEDIATE_FLOW;
}
......@@ -83,7 +103,7 @@ public class DefaultTypedFlowEntry extends DefaultFlowEntry
*
*/
public DefaultTypedFlowEntry(FlowEntry fe, FlowLiveType liveType) {
super(fe, fe.state(), fe.life(), fe.packets(), fe.bytes());
super(fe, fe.state(), fe.life(NANOSECONDS), NANOSECONDS, fe.packets(), fe.bytes());
this.liveType = liveType;
}
......
......@@ -16,6 +16,8 @@
package org.onosproject.net.flow;
import java.util.concurrent.TimeUnit;
/**
* Represents a generalized match & action pair to be applied to
* an infrastucture device.
......@@ -60,13 +62,20 @@ public interface FlowEntry extends FlowRule {
FlowEntryState state();
/**
* Returns the number of milliseconds this flow rule has been applied.
* Returns the number of seconds this flow rule has been applied.
*
* @return number of millis
* @return number of seconds
*/
long life();
/**
* Returns the time this flow rule has been applied.
*
* @return time in the requested {@link TimeUnit}
*/
long life(TimeUnit unit);
/**
* Returns the number of packets this flow rule has matched.
*
* @return number of packets
......
......@@ -16,6 +16,8 @@
package org.onosproject.net.flow;
import java.util.concurrent.TimeUnit;
public interface StoredFlowEntry extends FlowEntry {
/**
......@@ -31,9 +33,16 @@ public interface StoredFlowEntry extends FlowEntry {
/**
* Sets how long this entry has been entered in the system.
* @param life epoch time
* @param lifeSecs seconds
*/
void setLife(long lifeSecs);
/**
* Sets how long this entry has been entered in the system.
* @param life time
* @param timeUnit unit of time
*/
void setLife(long life);
void setLife(long life, TimeUnit timeUnit);
/**
* Number of packets seen by this entry.
......
......@@ -75,6 +75,9 @@ public class DefaultFlowEntryTest {
assertThat(defaultFlowEntry1.treatment(), is(TREATMENT));
assertThat(defaultFlowEntry1.timeout(), is(1));
assertThat(defaultFlowEntry1.life(), is(1L));
assertThat(defaultFlowEntry1.life(TimeUnit.SECONDS), is(1L));
assertThat(defaultFlowEntry1.life(TimeUnit.MILLISECONDS), is(1000L));
assertThat(defaultFlowEntry1.life(TimeUnit.MINUTES), is(0L));
assertThat(defaultFlowEntry1.packets(), is(1L));
assertThat(defaultFlowEntry1.bytes(), is(1L));
assertThat(defaultFlowEntry1.state(), is(FlowEntry.FlowEntryState.ADDED));
......@@ -94,13 +97,14 @@ public class DefaultFlowEntryTest {
entry.setState(FlowEntry.FlowEntryState.PENDING_REMOVE);
entry.setPackets(11);
entry.setBytes(22);
entry.setLife(33);
entry.setLife(33333, TimeUnit.MILLISECONDS);
assertThat(entry.deviceId(), is(did("id1")));
assertThat(entry.selector(), is(SELECTOR));
assertThat(entry.treatment(), is(TREATMENT));
assertThat(entry.timeout(), is(1));
assertThat(entry.life(), is(33L));
assertThat(entry.life(TimeUnit.MILLISECONDS), is(33333L));
assertThat(entry.packets(), is(11L));
assertThat(entry.bytes(), is(22L));
assertThat(entry.state(), is(FlowEntry.FlowEntryState.PENDING_REMOVE));
......
......@@ -51,7 +51,7 @@ public final class FlowEntryCodec extends JsonCodec<FlowEntry> {
.put("isPermanent", flowEntry.isPermanent())
.put("deviceId", flowEntry.deviceId().toString())
.put("state", flowEntry.state().toString())
.put("life", flowEntry.life())
.put("life", flowEntry.life()) //FIXME life is destroying precision (seconds granularity is default)
.put("packets", flowEntry.packets())
.put("bytes", flowEntry.bytes())
.put("lastSeen", flowEntry.lastSeen());
......
......@@ -569,7 +569,7 @@ public class DistributedFlowRuleStore
if (stored != null) {
//FIXME modification of "stored" flow entry outside of flow table
stored.setBytes(rule.bytes());
stored.setLife(rule.life());
stored.setLife(rule.life(TimeUnit.NANOSECONDS), TimeUnit.NANOSECONDS);
stored.setPackets(rule.packets());
stored.setLastSeen();
if (stored.state() == FlowEntryState.PENDING_ADD) {
......
......@@ -449,7 +449,7 @@ public class NewAdaptiveFlowStatsCollector implements SwitchDataCollector {
// update now
//FIXME modification of "stored" flow entry outside of store
stored.setLife(fe.life());
stored.setLife(fe.life(TimeUnit.NANOSECONDS), TimeUnit.NANOSECONDS);
stored.setPackets(fe.packets());
stored.setBytes(fe.bytes());
stored.setLastSeen();
......
......@@ -94,6 +94,8 @@ import org.slf4j.LoggerFactory;
import java.util.List;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.onosproject.net.flow.criteria.Criteria.*;
import static org.onosproject.net.flow.instructions.Instructions.modL0Lambda;
import static org.onosproject.net.flow.instructions.Instructions.modL1OduSignalId;
......@@ -170,7 +172,8 @@ public class FlowEntryBuilder {
}
return new DefaultFlowEntry(builder.build(), FlowEntryState.ADDED,
stat.getDurationSec(),
SECONDS.toNanos(stat.getDurationSec())
+ stat.getDurationNsec(), NANOSECONDS,
stat.getPacketCount().getValue(),
stat.getByteCount().getValue());
case REMOVED:
......@@ -185,7 +188,8 @@ public class FlowEntryBuilder {
}
return new DefaultFlowEntry(builder.build(), FlowEntryState.REMOVED,
removed.getDurationSec(),
SECONDS.toNanos(removed.getDurationSec())
+ removed.getDurationNsec(), NANOSECONDS,
removed.getPacketCount().getValue(),
removed.getByteCount().getValue());
case MOD:
......
......@@ -64,7 +64,9 @@ import java.net.HttpURLConnection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.anyShort;
import static org.easymock.EasyMock.anyString;
......@@ -141,7 +143,12 @@ public class FlowsResourceTest extends ResourceTest {
@Override
public long life() {
return baseValue + 11;
return life(SECONDS);
}
@Override
public long life(TimeUnit timeUnit) {
return SECONDS.convert(baseValue + 11, timeUnit);
}
@Override
......