diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java index d38d044d7b..d258a74ecf 100644 --- a/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java +++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultFlowRule.java @@ -46,6 +46,8 @@ public class DefaultFlowRule implements FlowRule { private final int timeout; private final boolean permanent; + private final int hardTimeout; + private final FlowRemoveReason reason; private final GroupId groupId; private final Integer tableId; @@ -60,6 +62,8 @@ public class DefaultFlowRule implements FlowRule { this.groupId = rule.groupId(); this.id = rule.id(); this.timeout = rule.timeout(); + this.hardTimeout = rule.hardTimeout(); + this.reason = rule.reason(); this.permanent = rule.isPermanent(); this.created = System.currentTimeMillis(); this.tableId = rule.tableId(); @@ -68,8 +72,8 @@ public class DefaultFlowRule implements FlowRule { private DefaultFlowRule(DeviceId deviceId, TrafficSelector selector, TrafficTreatment treatment, Integer priority, - FlowId flowId, Boolean permanent, Integer timeout, - Integer tableId) { + FlowId flowId, Boolean permanent, Integer timeout, Integer hardTimeout, + FlowRemoveReason reason, Integer tableId) { this.deviceId = deviceId; this.selector = selector; @@ -79,6 +83,8 @@ public class DefaultFlowRule implements FlowRule { this.id = flowId; this.permanent = permanent; this.timeout = timeout; + this.hardTimeout = hardTimeout; + this.reason = reason; this.tableId = tableId; this.created = System.currentTimeMillis(); @@ -88,6 +94,8 @@ public class DefaultFlowRule implements FlowRule { this.payLoad = null; } + + /** * 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, ApplicationId appId, int timeout, boolean permanent, 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 " + MIN_PRIORITY); @@ -118,6 +148,8 @@ public class DefaultFlowRule implements FlowRule { this.appId = appId.id(); this.groupId = new DefaultGroupId(0); this.timeout = timeout; + this.reason = FlowRemoveReason.NO_REASON; + this.hardTimeout = hardTimeout; this.permanent = permanent; this.tableId = 0; this.created = System.currentTimeMillis(); @@ -152,6 +184,30 @@ public class DefaultFlowRule implements FlowRule { TrafficTreatment treatment, int priority, ApplicationId appId, GroupId groupId, int timeout, 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 " + MIN_PRIORITY); @@ -165,6 +221,8 @@ public class DefaultFlowRule implements FlowRule { this.appId = appId.id(); this.groupId = groupId; this.timeout = timeout; + this.reason = FlowRemoveReason.NO_REASON; + this.hardTimeout = hardTimeout; this.permanent = permanent; this.created = System.currentTimeMillis(); this.tableId = 0; @@ -280,6 +338,18 @@ public class DefaultFlowRule implements FlowRule { return timeout; } + + + @Override + public int hardTimeout() { + return hardTimeout; + } + + @Override + public FlowRemoveReason reason() { + return reason; + } + @Override public boolean isPermanent() { return permanent; @@ -310,6 +380,8 @@ public class DefaultFlowRule implements FlowRule { private TrafficTreatment treatment = DefaultTrafficTreatment.builder().build(); private Integer timeout; private Boolean permanent; + private Integer hardTimeout = 0; + private FlowRemoveReason reason = FlowRemoveReason.NO_REASON; @Override public FlowRule.Builder withCookie(long cookie) { @@ -367,6 +439,20 @@ public class DefaultFlowRule implements FlowRule { 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 public FlowRule build() { FlowId localFlowId; @@ -390,7 +476,7 @@ public class DefaultFlowRule implements FlowRule { } return new DefaultFlowRule(deviceId, selector, treatment, priority, - localFlowId, permanent, timeout, tableId); + localFlowId, permanent, timeout, hardTimeout, reason, tableId); } private FlowId computeFlowId(ApplicationId appId) { diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java b/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java index ecec89cafa..35804b8f09 100644 --- a/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java +++ b/core/api/src/main/java/org/onosproject/net/flow/FlowRule.java @@ -29,6 +29,28 @@ public interface FlowRule { int MIN_PRIORITY = 0; 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. * @@ -87,6 +109,21 @@ public interface FlowRule { */ 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. * @@ -211,6 +248,20 @@ public interface FlowRule { */ 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. * diff --git a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java index 471546e6ba..c090faed3f 100644 --- a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java +++ b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java @@ -26,6 +26,7 @@ import org.onosproject.net.Link; import org.onosproject.net.NetTestTools; import org.onosproject.net.NetworkResource; import org.onosproject.net.Path; +import org.onosproject.net.flow.FlowRule.FlowRemoveReason; import org.onosproject.net.flow.FlowId; import org.onosproject.net.flow.FlowRule; import org.onosproject.net.flow.FlowRuleExtPayLoad; @@ -329,6 +330,16 @@ public class IntentTestsMocks { return 0; } + @Override + public int hardTimeout() { + return 0; + } + + @Override + public FlowRemoveReason reason() { + return FlowRemoveReason.NO_REASON; + } + @Override public boolean isPermanent() { return false; diff --git a/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java b/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java index a61b1502a2..74524ac86e 100644 --- a/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java +++ b/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java @@ -313,8 +313,10 @@ public class FlowRuleManager extends AbstractProviderService implements FlowRuleProviderService { + final Map firstSeen = Maps.newConcurrentMap(); final Map lastSeen = Maps.newConcurrentMap(); + protected InternalFlowRuleProviderService(FlowRuleProvider provider) { super(provider); } @@ -324,11 +326,15 @@ public class FlowRuleManager checkNotNull(flowEntry, FLOW_RULE_NULL); checkValidity(); lastSeen.remove(flowEntry); + firstSeen.remove(flowEntry); FlowEntry stored = store.getFlowEntry(flowEntry); if (stored == null) { log.debug("Rule already evicted from store: {}", flowEntry); return; } + if (flowEntry.reason() == FlowEntry.FlowRemoveReason.HARD_TIMEOUT) { + ((DefaultFlowEntry) stored).setState(FlowEntry.FlowEntryState.REMOVED); + } Device device = deviceService.getDevice(flowEntry.deviceId()); FlowRuleProvider frp = getProvider(device.providerId()); FlowRuleEvent event = null; @@ -422,6 +428,21 @@ public class FlowRuleManager final long timeout = storedRule.timeout() * 1000; 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()) { lastSeen.put(storedRule, currentTime); return true; diff --git a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java index 74ad5d8b8e..60030eed14 100644 --- a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java +++ b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java @@ -101,6 +101,7 @@ import org.onosproject.net.flow.DefaultTrafficSelector; import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.FlowEntry; import org.onosproject.net.flow.FlowId; +import org.onosproject.net.flow.FlowRule; import org.onosproject.net.flow.FlowRuleBatchEntry; import org.onosproject.net.flow.FlowRuleBatchEvent; import org.onosproject.net.flow.FlowRuleBatchOperation; @@ -349,6 +350,7 @@ public final class KryoNamespaces { DefaultFlowEntry.class, StoredFlowEntry.class, DefaultFlowRule.class, + FlowRule.FlowRemoveReason.class, DefaultPacketRequest.class, PacketPriority.class, FlowEntry.FlowEntryState.class, diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java index b41f6ce30c..c02674f098 100644 --- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java +++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java @@ -95,6 +95,7 @@ public class FlowModBuilderVer10 extends FlowModBuilder { .setMatch(match) .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM)) .setPriority(flowRule().priority()) + .setHardTimeout(flowRule().hardTimeout()) .build(); return fm; @@ -115,6 +116,7 @@ public class FlowModBuilderVer10 extends FlowModBuilder { .setMatch(match) .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM)) .setPriority(flowRule().priority()) + .setHardTimeout(flowRule().hardTimeout()) .build(); return fm; @@ -133,6 +135,7 @@ public class FlowModBuilderVer10 extends FlowModBuilder { .setMatch(match) .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM)) .setPriority(flowRule().priority()) + .setHardTimeout(flowRule().hardTimeout()) .build(); return fm; diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java index cd96472978..44b839b4bf 100644 --- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java +++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java @@ -158,6 +158,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder { .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM)) .setPriority(flowRule().priority()) .setTableId(TableId.of(flowRule().tableId())) + .setHardTimeout(flowRule().hardTimeout()) .build(); return fm; @@ -201,6 +202,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder { .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM)) .setPriority(flowRule().priority()) .setTableId(TableId.of(flowRule().tableId())) + .setHardTimeout(flowRule().hardTimeout()) .build(); return fm; @@ -220,6 +222,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder { .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM)) .setPriority(flowRule().priority()) .setTableId(TableId.of(flowRule().tableId())) + .setHardTimeout(flowRule().hardTimeout()) .build(); return fm; diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java index 54f704f7c7..e40990e01c 100644 --- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java +++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java @@ -182,7 +182,9 @@ public class FlowEntryBuilder { .withSelector(buildSelector()) .withPriority(removed.getPriority()) .makeTemporary(removed.getIdleTimeout()) - .withCookie(removed.getCookie().getValue()); + .withCookie(removed.getCookie().getValue()) + .withReason(FlowRule.FlowRemoveReason.parseShort(removed.getReason())); + if (removed.getVersion() != OFVersion.OF_10) { builder.forTable(removed.getTableId().getValue()); } diff --git a/web/api/src/test/java/org/onosproject/rest/resources/FlowsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/FlowsResourceTest.java index 68dc39391f..2ecd373cee 100644 --- a/web/api/src/test/java/org/onosproject/rest/resources/FlowsResourceTest.java +++ b/web/api/src/test/java/org/onosproject/rest/resources/FlowsResourceTest.java @@ -46,6 +46,7 @@ import org.onosproject.net.flow.DefaultTrafficSelector; import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.FlowEntry; import org.onosproject.net.flow.FlowId; +import org.onosproject.net.flow.FlowRule.FlowRemoveReason; import org.onosproject.net.flow.FlowRule; import org.onosproject.net.flow.FlowRuleExtPayLoad; import org.onosproject.net.flow.FlowRuleService; @@ -217,6 +218,16 @@ public class FlowsResourceTest extends ResourceTest { return (int) (baseValue + 77); } + @Override + public int hardTimeout() { + return 0; + } + + @Override + public FlowRemoveReason reason() { + return FlowRemoveReason.NO_REASON; + } + @Override public boolean isPermanent() { return false; @@ -294,6 +305,16 @@ public class FlowsResourceTest extends ResourceTest { return (int) (baseValue + 77); } + @Override + public int hardTimeout() { + return 0; + } + + @Override + public FlowRemoveReason reason() { + return FlowRemoveReason.NO_REASON; + } + @Override public boolean isPermanent() { return false;