ONOS-4374 Enable installing flows with hard_timeout

Change-Id: I4e60e93aad44c7e8f8913fa4dd3ed5a2565d7034
This commit is contained in:
Murat Parlakisik 2016-06-29 03:22:22 -07:00 committed by Gerrit Code Review
parent 9bdaaecaf0
commit c6759e80bd
9 changed files with 204 additions and 4 deletions

View File

@ -46,6 +46,8 @@ public class DefaultFlowRule implements FlowRule {
private final int timeout; private final int timeout;
private final boolean permanent; private final boolean permanent;
private final int hardTimeout;
private final FlowRemoveReason reason;
private final GroupId groupId; private final GroupId groupId;
private final Integer tableId; private final Integer tableId;
@ -60,6 +62,8 @@ public class DefaultFlowRule implements FlowRule {
this.groupId = rule.groupId(); this.groupId = rule.groupId();
this.id = rule.id(); this.id = rule.id();
this.timeout = rule.timeout(); this.timeout = rule.timeout();
this.hardTimeout = rule.hardTimeout();
this.reason = rule.reason();
this.permanent = rule.isPermanent(); this.permanent = rule.isPermanent();
this.created = System.currentTimeMillis(); this.created = System.currentTimeMillis();
this.tableId = rule.tableId(); this.tableId = rule.tableId();
@ -68,8 +72,8 @@ public class DefaultFlowRule implements FlowRule {
private DefaultFlowRule(DeviceId deviceId, TrafficSelector selector, private DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
TrafficTreatment treatment, Integer priority, TrafficTreatment treatment, Integer priority,
FlowId flowId, Boolean permanent, Integer timeout, FlowId flowId, Boolean permanent, Integer timeout, Integer hardTimeout,
Integer tableId) { FlowRemoveReason reason, Integer tableId) {
this.deviceId = deviceId; this.deviceId = deviceId;
this.selector = selector; this.selector = selector;
@ -79,6 +83,8 @@ public class DefaultFlowRule implements FlowRule {
this.id = flowId; this.id = flowId;
this.permanent = permanent; this.permanent = permanent;
this.timeout = timeout; this.timeout = timeout;
this.hardTimeout = hardTimeout;
this.reason = reason;
this.tableId = tableId; this.tableId = tableId;
this.created = System.currentTimeMillis(); this.created = System.currentTimeMillis();
@ -88,6 +94,8 @@ public class DefaultFlowRule implements FlowRule {
this.payLoad = null; this.payLoad = null;
} }
/** /**
* Support for the third party flow rule. Creates a flow rule of flow table. * Support for the third party flow rule. Creates a flow rule of flow table.
* *
@ -105,6 +113,28 @@ public class DefaultFlowRule implements FlowRule {
TrafficTreatment treatment, int priority, TrafficTreatment treatment, int priority,
ApplicationId appId, int timeout, boolean permanent, ApplicationId appId, int timeout, boolean permanent,
FlowRuleExtPayLoad payLoad) { FlowRuleExtPayLoad payLoad) {
this(deviceId, selector, treatment, priority, appId, timeout, 0, permanent, payLoad);
}
/**
* Support for the third party flow rule. Creates a flow rule of flow table.
*
* @param deviceId the identity of the device where this rule applies
* @param selector the traffic selector that identifies what traffic this
* rule
* @param treatment the traffic treatment that applies to selected traffic
* @param priority the flow rule priority given in natural order
* @param appId the application id of this flow
* @param timeout the timeout for this flow requested by an application
* @param hardTimeout the hard timeout located switch's flow table for this flow requested by an application
* @param permanent whether the flow is permanent i.e. does not time out
* @param payLoad 3rd-party origin private flow
*/
public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
TrafficTreatment treatment, int priority,
ApplicationId appId, int timeout, int hardTimeout, boolean permanent,
FlowRuleExtPayLoad payLoad) {
checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " + checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
MIN_PRIORITY); MIN_PRIORITY);
@ -118,6 +148,8 @@ public class DefaultFlowRule implements FlowRule {
this.appId = appId.id(); this.appId = appId.id();
this.groupId = new DefaultGroupId(0); this.groupId = new DefaultGroupId(0);
this.timeout = timeout; this.timeout = timeout;
this.reason = FlowRemoveReason.NO_REASON;
this.hardTimeout = hardTimeout;
this.permanent = permanent; this.permanent = permanent;
this.tableId = 0; this.tableId = 0;
this.created = System.currentTimeMillis(); this.created = System.currentTimeMillis();
@ -152,6 +184,30 @@ public class DefaultFlowRule implements FlowRule {
TrafficTreatment treatment, int priority, TrafficTreatment treatment, int priority,
ApplicationId appId, GroupId groupId, int timeout, ApplicationId appId, GroupId groupId, int timeout,
boolean permanent, FlowRuleExtPayLoad payLoad) { boolean permanent, FlowRuleExtPayLoad payLoad) {
this(deviceId, selector, treatment, priority, appId, groupId, timeout, 0, permanent, payLoad);
}
/**
* Support for the third party flow rule. Creates a flow rule of group
* table.
*
* @param deviceId the identity of the device where this rule applies
* @param selector the traffic selector that identifies what traffic this
* rule
* @param treatment the traffic treatment that applies to selected traffic
* @param priority the flow rule priority given in natural order
* @param appId the application id of this flow
* @param groupId the group id of this flow
* @param timeout the timeout for this flow requested by an application
* @param hardTimeout the hard timeout located switch's flow table for this flow requested by an application
* @param permanent whether the flow is permanent i.e. does not time out
* @param payLoad 3rd-party origin private flow
*
*/
public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
TrafficTreatment treatment, int priority,
ApplicationId appId, GroupId groupId, int timeout, int hardTimeout,
boolean permanent, FlowRuleExtPayLoad payLoad) {
checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " + checkArgument(priority >= MIN_PRIORITY, "Priority cannot be less than " +
MIN_PRIORITY); MIN_PRIORITY);
@ -165,6 +221,8 @@ public class DefaultFlowRule implements FlowRule {
this.appId = appId.id(); this.appId = appId.id();
this.groupId = groupId; this.groupId = groupId;
this.timeout = timeout; this.timeout = timeout;
this.reason = FlowRemoveReason.NO_REASON;
this.hardTimeout = hardTimeout;
this.permanent = permanent; this.permanent = permanent;
this.created = System.currentTimeMillis(); this.created = System.currentTimeMillis();
this.tableId = 0; this.tableId = 0;
@ -280,6 +338,18 @@ public class DefaultFlowRule implements FlowRule {
return timeout; return timeout;
} }
@Override
public int hardTimeout() {
return hardTimeout;
}
@Override
public FlowRemoveReason reason() {
return reason;
}
@Override @Override
public boolean isPermanent() { public boolean isPermanent() {
return permanent; return permanent;
@ -310,6 +380,8 @@ public class DefaultFlowRule implements FlowRule {
private TrafficTreatment treatment = DefaultTrafficTreatment.builder().build(); private TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
private Integer timeout; private Integer timeout;
private Boolean permanent; private Boolean permanent;
private Integer hardTimeout = 0;
private FlowRemoveReason reason = FlowRemoveReason.NO_REASON;
@Override @Override
public FlowRule.Builder withCookie(long cookie) { public FlowRule.Builder withCookie(long cookie) {
@ -367,6 +439,20 @@ public class DefaultFlowRule implements FlowRule {
return this; return this;
} }
@Override
public FlowRule.Builder withHardTimeout(int timeout) {
this.permanent = false;
this.hardTimeout = timeout;
this.timeout = timeout;
return this;
}
@Override
public FlowRule.Builder withReason(FlowRemoveReason reason) {
this.reason = reason;
return this;
}
@Override @Override
public FlowRule build() { public FlowRule build() {
FlowId localFlowId; FlowId localFlowId;
@ -390,7 +476,7 @@ public class DefaultFlowRule implements FlowRule {
} }
return new DefaultFlowRule(deviceId, selector, treatment, priority, return new DefaultFlowRule(deviceId, selector, treatment, priority,
localFlowId, permanent, timeout, tableId); localFlowId, permanent, timeout, hardTimeout, reason, tableId);
} }
private FlowId computeFlowId(ApplicationId appId) { private FlowId computeFlowId(ApplicationId appId) {

View File

@ -29,6 +29,28 @@ public interface FlowRule {
int MIN_PRIORITY = 0; int MIN_PRIORITY = 0;
int MAX_PRIORITY = 65535; int MAX_PRIORITY = 65535;
/**
* Reason for flow parameter received from switches.
* Used to check reason parameter in flows.
*/
enum FlowRemoveReason {
NO_REASON,
IDLE_TIMEOUT,
HARD_TIMEOUT;
public static FlowRemoveReason parseShort(short reason) {
switch (reason) {
case -1 :
return NO_REASON;
case 0:
return IDLE_TIMEOUT;
case 1:
return HARD_TIMEOUT;
default :
return NO_REASON;
}
}
}
/** /**
* Returns the ID of this flow. * Returns the ID of this flow.
* *
@ -87,6 +109,21 @@ public interface FlowRule {
*/ */
int timeout(); int timeout();
/**
* Returns the hard timeout for this flow requested by an application.
* This paremeter configure switch's flow hard timeout.
* In case of controller-switch connection lost, this variable can be useful.
* @return integer value of the hard Timeout
*/
int hardTimeout();
/**
* Returns the reason for the flow received from switches.
*
* @return FlowRemoveReason value of reason
*/
FlowRemoveReason reason();
/** /**
* Returns whether the flow is permanent i.e. does not time out. * Returns whether the flow is permanent i.e. does not time out.
* *
@ -211,6 +248,20 @@ public interface FlowRule {
*/ */
Builder makeTemporary(int timeout); Builder makeTemporary(int timeout);
/**
* Sets hard timeout parameter in flow table.
* @param timeout an integer
* @return this
*/
Builder withHardTimeout(int timeout);
/**
* Sets reason parameter received from switches .
* @param reason a short
* @return this
*/
Builder withReason(FlowRemoveReason reason);
/** /**
* Builds a flow rule object. * Builds a flow rule object.
* *

View File

@ -26,6 +26,7 @@ import org.onosproject.net.Link;
import org.onosproject.net.NetTestTools; import org.onosproject.net.NetTestTools;
import org.onosproject.net.NetworkResource; import org.onosproject.net.NetworkResource;
import org.onosproject.net.Path; import org.onosproject.net.Path;
import org.onosproject.net.flow.FlowRule.FlowRemoveReason;
import org.onosproject.net.flow.FlowId; import org.onosproject.net.flow.FlowId;
import org.onosproject.net.flow.FlowRule; import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleExtPayLoad; import org.onosproject.net.flow.FlowRuleExtPayLoad;
@ -329,6 +330,16 @@ public class IntentTestsMocks {
return 0; return 0;
} }
@Override
public int hardTimeout() {
return 0;
}
@Override
public FlowRemoveReason reason() {
return FlowRemoveReason.NO_REASON;
}
@Override @Override
public boolean isPermanent() { public boolean isPermanent() {
return false; return false;

View File

@ -313,8 +313,10 @@ public class FlowRuleManager
extends AbstractProviderService<FlowRuleProvider> extends AbstractProviderService<FlowRuleProvider>
implements FlowRuleProviderService { implements FlowRuleProviderService {
final Map<FlowEntry, Long> firstSeen = Maps.newConcurrentMap();
final Map<FlowEntry, Long> lastSeen = Maps.newConcurrentMap(); final Map<FlowEntry, Long> lastSeen = Maps.newConcurrentMap();
protected InternalFlowRuleProviderService(FlowRuleProvider provider) { protected InternalFlowRuleProviderService(FlowRuleProvider provider) {
super(provider); super(provider);
} }
@ -324,11 +326,15 @@ public class FlowRuleManager
checkNotNull(flowEntry, FLOW_RULE_NULL); checkNotNull(flowEntry, FLOW_RULE_NULL);
checkValidity(); checkValidity();
lastSeen.remove(flowEntry); lastSeen.remove(flowEntry);
firstSeen.remove(flowEntry);
FlowEntry stored = store.getFlowEntry(flowEntry); FlowEntry stored = store.getFlowEntry(flowEntry);
if (stored == null) { if (stored == null) {
log.debug("Rule already evicted from store: {}", flowEntry); log.debug("Rule already evicted from store: {}", flowEntry);
return; return;
} }
if (flowEntry.reason() == FlowEntry.FlowRemoveReason.HARD_TIMEOUT) {
((DefaultFlowEntry) stored).setState(FlowEntry.FlowEntryState.REMOVED);
}
Device device = deviceService.getDevice(flowEntry.deviceId()); Device device = deviceService.getDevice(flowEntry.deviceId());
FlowRuleProvider frp = getProvider(device.providerId()); FlowRuleProvider frp = getProvider(device.providerId());
FlowRuleEvent event = null; FlowRuleEvent event = null;
@ -422,6 +428,21 @@ public class FlowRuleManager
final long timeout = storedRule.timeout() * 1000; final long timeout = storedRule.timeout() * 1000;
final long currentTime = System.currentTimeMillis(); final long currentTime = System.currentTimeMillis();
// Checking flow with hardTimeout
if (storedRule.hardTimeout() != 0) {
if (!firstSeen.containsKey(storedRule)) {
// First time rule adding
firstSeen.put(storedRule, currentTime);
} else {
Long first = firstSeen.get(storedRule);
final long hardTimeout = storedRule.hardTimeout() * 1000;
if ((currentTime - first) > hardTimeout) {
return false;
}
}
}
if (storedRule.packets() != swRule.packets()) { if (storedRule.packets() != swRule.packets()) {
lastSeen.put(storedRule, currentTime); lastSeen.put(storedRule, currentTime);
return true; return true;

View File

@ -101,6 +101,7 @@ import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowEntry; import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowId; import org.onosproject.net.flow.FlowId;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleBatchEntry; import org.onosproject.net.flow.FlowRuleBatchEntry;
import org.onosproject.net.flow.FlowRuleBatchEvent; import org.onosproject.net.flow.FlowRuleBatchEvent;
import org.onosproject.net.flow.FlowRuleBatchOperation; import org.onosproject.net.flow.FlowRuleBatchOperation;
@ -349,6 +350,7 @@ public final class KryoNamespaces {
DefaultFlowEntry.class, DefaultFlowEntry.class,
StoredFlowEntry.class, StoredFlowEntry.class,
DefaultFlowRule.class, DefaultFlowRule.class,
FlowRule.FlowRemoveReason.class,
DefaultPacketRequest.class, DefaultPacketRequest.class,
PacketPriority.class, PacketPriority.class,
FlowEntry.FlowEntryState.class, FlowEntry.FlowEntryState.class,

View File

@ -95,6 +95,7 @@ public class FlowModBuilderVer10 extends FlowModBuilder {
.setMatch(match) .setMatch(match)
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM)) .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority()) .setPriority(flowRule().priority())
.setHardTimeout(flowRule().hardTimeout())
.build(); .build();
return fm; return fm;
@ -115,6 +116,7 @@ public class FlowModBuilderVer10 extends FlowModBuilder {
.setMatch(match) .setMatch(match)
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM)) .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority()) .setPriority(flowRule().priority())
.setHardTimeout(flowRule().hardTimeout())
.build(); .build();
return fm; return fm;
@ -133,6 +135,7 @@ public class FlowModBuilderVer10 extends FlowModBuilder {
.setMatch(match) .setMatch(match)
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM)) .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority()) .setPriority(flowRule().priority())
.setHardTimeout(flowRule().hardTimeout())
.build(); .build();
return fm; return fm;

View File

@ -158,6 +158,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM)) .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority()) .setPriority(flowRule().priority())
.setTableId(TableId.of(flowRule().tableId())) .setTableId(TableId.of(flowRule().tableId()))
.setHardTimeout(flowRule().hardTimeout())
.build(); .build();
return fm; return fm;
@ -201,6 +202,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM)) .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority()) .setPriority(flowRule().priority())
.setTableId(TableId.of(flowRule().tableId())) .setTableId(TableId.of(flowRule().tableId()))
.setHardTimeout(flowRule().hardTimeout())
.build(); .build();
return fm; return fm;
@ -220,6 +222,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
.setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM)) .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
.setPriority(flowRule().priority()) .setPriority(flowRule().priority())
.setTableId(TableId.of(flowRule().tableId())) .setTableId(TableId.of(flowRule().tableId()))
.setHardTimeout(flowRule().hardTimeout())
.build(); .build();
return fm; return fm;

View File

@ -182,7 +182,9 @@ public class FlowEntryBuilder {
.withSelector(buildSelector()) .withSelector(buildSelector())
.withPriority(removed.getPriority()) .withPriority(removed.getPriority())
.makeTemporary(removed.getIdleTimeout()) .makeTemporary(removed.getIdleTimeout())
.withCookie(removed.getCookie().getValue()); .withCookie(removed.getCookie().getValue())
.withReason(FlowRule.FlowRemoveReason.parseShort(removed.getReason()));
if (removed.getVersion() != OFVersion.OF_10) { if (removed.getVersion() != OFVersion.OF_10) {
builder.forTable(removed.getTableId().getValue()); builder.forTable(removed.getTableId().getValue());
} }

View File

@ -46,6 +46,7 @@ import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowEntry; import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowId; import org.onosproject.net.flow.FlowId;
import org.onosproject.net.flow.FlowRule.FlowRemoveReason;
import org.onosproject.net.flow.FlowRule; import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleExtPayLoad; import org.onosproject.net.flow.FlowRuleExtPayLoad;
import org.onosproject.net.flow.FlowRuleService; import org.onosproject.net.flow.FlowRuleService;
@ -217,6 +218,16 @@ public class FlowsResourceTest extends ResourceTest {
return (int) (baseValue + 77); return (int) (baseValue + 77);
} }
@Override
public int hardTimeout() {
return 0;
}
@Override
public FlowRemoveReason reason() {
return FlowRemoveReason.NO_REASON;
}
@Override @Override
public boolean isPermanent() { public boolean isPermanent() {
return false; return false;
@ -294,6 +305,16 @@ public class FlowsResourceTest extends ResourceTest {
return (int) (baseValue + 77); return (int) (baseValue + 77);
} }
@Override
public int hardTimeout() {
return 0;
}
@Override
public FlowRemoveReason reason() {
return FlowRemoveReason.NO_REASON;
}
@Override @Override
public boolean isPermanent() { public boolean isPermanent() {
return false; return false;