Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 4494709..9d8259e 100644
--- a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -2,6 +2,9 @@
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command>
+ <action class="org.onlab.onos.cli.net.FlowsListCommand"/>
+ </command>
+ <command>
<action class="org.onlab.onos.cli.net.DevicesListCommand"/>
</command>
<command>
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java
index fae1fe3..62e331f 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/DefaultFlowRule.java
@@ -15,19 +15,20 @@
private final FlowId id;
private final long created;
private final long life;
- private final long idle;
private final long packets;
private final long bytes;
+ private final FlowRuleState state;
public DefaultFlowRule(DeviceId deviceId,
- TrafficSelector selector, TrafficTreatment treatment, int priority) {
+ TrafficSelector selector, TrafficTreatment treatment,
+ int priority, FlowRuleState state) {
this.deviceId = deviceId;
this.priority = priority;
this.selector = selector;
this.treatment = treatment;
+ this.state = state;
this.life = 0;
- this.idle = 0;
this.packets = 0;
this.bytes = 0;
this.id = FlowId.valueOf(this.hashCode());
@@ -35,22 +36,32 @@
}
public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
- TrafficTreatment treatment, int priority,
- long life, long idle, long packets, long bytes, Integer flowId) {
+ TrafficTreatment treatment, int priority, FlowRuleState state,
+ long life, long packets, long bytes, Integer flowId) {
this.deviceId = deviceId;
this.priority = priority;
this.selector = selector;
this.treatment = treatment;
+ this.state = state;
this.id = FlowId.valueOf(flowId);
this.life = life;
- this.idle = idle;
this.packets = packets;
this.bytes = bytes;
this.created = System.currentTimeMillis();
}
+ public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
+ TrafficTreatment treatement, int priority) {
+ this(deviceId, selector, treatement, priority, FlowRuleState.CREATED);
+ }
+
+ public DefaultFlowRule(FlowRule rule, FlowRuleState state) {
+ this(rule.deviceId(), rule.selector(), rule.treatment(),
+ rule.priority(), state);
+ }
+
@Override
public FlowId id() {
@@ -83,11 +94,6 @@
}
@Override
- public long idleMillis() {
- return idle;
- }
-
- @Override
public long packets() {
return packets;
}
@@ -98,6 +104,12 @@
}
@Override
+ public FlowRuleState state() {
+ return this.state;
+ }
+
+
+ @Override
/*
* The priority and statistics can change on a given treatment and selector
*
@@ -116,19 +128,14 @@
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
- if (obj instanceof FlowRule) {
- DefaultFlowRule that = (DefaultFlowRule) obj;
- if (!this.deviceId().equals(that.deviceId())) {
- return false;
- }
- if (!this.treatment().equals(that.treatment())) {
- return false;
- }
- if (!this.selector().equals(that.selector())) {
- return false;
- }
+ if (this == obj) {
return true;
}
+ if (obj instanceof FlowRule) {
+ FlowRule that = (FlowRule) obj;
+ return Objects.equals(deviceId, that.deviceId()) &&
+ Objects.equals(id, that.id());
+ }
return false;
}
@@ -144,5 +151,4 @@
.toString();
}
-
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/FlowId.java b/core/api/src/main/java/org/onlab/onos/net/flow/FlowId.java
index 03140f7..c7c44cb 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/FlowId.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/FlowId.java
@@ -1,13 +1,15 @@
package org.onlab.onos.net.flow;
+import com.google.common.base.Objects;
+
/**
* Representation of a Flow ID.
*/
public final class FlowId {
- private final int flowid;
+ private final long flowid;
- private FlowId(int id) {
+ private FlowId(long id) {
this.flowid = id;
}
@@ -15,7 +17,24 @@
return new FlowId(id);
}
- public int value() {
+ public long value() {
return flowid;
}
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj.getClass() == this.getClass()) {
+ FlowId that = (FlowId) obj;
+ return Objects.equal(this.flowid, that.flowid);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(this.flowid);
+ }
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRule.java b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRule.java
index f2bc1a0..e72beed 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRule.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRule.java
@@ -8,6 +8,42 @@
*/
public interface FlowRule {
+
+ public enum FlowRuleState {
+ /**
+ * Indicates that this rule has been created.
+ */
+ CREATED,
+
+ /**
+ * Indicates that this rule has been submitted for addition.
+ * Not necessarily in the flow table.
+ */
+ PENDING_ADD,
+
+ /**
+ * Rule has been added which means it is in the flow table.
+ */
+ ADDED,
+
+ /**
+ * Flow has been marked for removal, might still be in flow table.
+ */
+ PENDING_REMOVE,
+
+ /**
+ * Flow has been removed from flow table and can be purged.
+ */
+ REMOVED
+ }
+
+ /**
+ * Returns the flow rule state.
+ *
+ * @return flow rule state
+ */
+ FlowRuleState state();
+
//TODO: build cookie value
/**
* Returns the ID of this flow.
@@ -54,13 +90,6 @@
long lifeMillis();
/**
- * Returns the number of milliseconds this flow rule has been idle.
- *
- * @return number of millis
- */
- long idleMillis();
-
- /**
* Returns the number of packets this flow rule has matched.
*
* @return number of packets
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProviderService.java b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProviderService.java
index 737ac28..df988fe 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProviderService.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProviderService.java
@@ -1,5 +1,6 @@
package org.onlab.onos.net.flow;
+import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.provider.ProviderService;
/**
@@ -35,6 +36,6 @@
*
* @param flowRules collection of flow rules
*/
- void pushFlowMetrics(Iterable<FlowRule> flowRules);
+ void pushFlowMetrics(DeviceId deviceId, Iterable<FlowRule> flowRules);
}
diff --git a/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java b/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
index 41f7303..5bd6fed 100644
--- a/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
@@ -4,6 +4,7 @@
import static org.slf4j.LoggerFactory.getLogger;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import org.apache.felix.scr.annotations.Activate;
@@ -17,7 +18,9 @@
import org.onlab.onos.net.Device;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.DeviceService;
+import org.onlab.onos.net.flow.DefaultFlowRule;
import org.onlab.onos.net.flow.FlowRule;
+import org.onlab.onos.net.flow.FlowRule.FlowRuleState;
import org.onlab.onos.net.flow.FlowRuleEvent;
import org.onlab.onos.net.flow.FlowRuleListener;
import org.onlab.onos.net.flow.FlowRuleProvider;
@@ -29,17 +32,19 @@
import org.onlab.onos.net.provider.AbstractProviderService;
import org.slf4j.Logger;
+import com.google.common.collect.Lists;
+
@Component(immediate = true)
@Service
public class FlowRuleManager
- extends AbstractProviderRegistry<FlowRuleProvider, FlowRuleProviderService>
- implements FlowRuleService, FlowRuleProviderRegistry {
+extends AbstractProviderRegistry<FlowRuleProvider, FlowRuleProviderService>
+implements FlowRuleService, FlowRuleProviderRegistry {
public static final String FLOW_RULE_NULL = "FlowRule cannot be null";
private final Logger log = getLogger(getClass());
private final AbstractListenerRegistry<FlowRuleEvent, FlowRuleListener>
- listenerRegistry = new AbstractListenerRegistry<>();
+ listenerRegistry = new AbstractListenerRegistry<>();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected FlowRuleStore store;
@@ -72,7 +77,7 @@
List<FlowRule> entries = new ArrayList<FlowRule>();
for (int i = 0; i < flowRules.length; i++) {
- FlowRule f = flowRules[i];
+ FlowRule f = new DefaultFlowRule(flowRules[i], FlowRuleState.PENDING_ADD);
final Device device = deviceService.getDevice(f.deviceId());
final FlowRuleProvider frp = getProvider(device.providerId());
entries.add(store.storeFlowRule(f));
@@ -85,7 +90,7 @@
@Override
public void removeFlowRules(FlowRule... flowRules) {
for (int i = 0; i < flowRules.length; i++) {
- FlowRule f = flowRules[i];
+ FlowRule f = new DefaultFlowRule(flowRules[i], FlowRuleState.PENDING_REMOVE);
final Device device = deviceService.getDevice(f.deviceId());
final FlowRuleProvider frp = getProvider(device.providerId());
store.removeFlowRule(f);
@@ -111,8 +116,8 @@
}
private class InternalFlowRuleProviderService
- extends AbstractProviderService<FlowRuleProvider>
- implements FlowRuleProviderService {
+ extends AbstractProviderService<FlowRuleProvider>
+ implements FlowRuleProviderService {
protected InternalFlowRuleProviderService(FlowRuleProvider provider) {
super(provider);
@@ -160,8 +165,32 @@
}
@Override
- public void pushFlowMetrics(Iterable<FlowRule> flowEntries) {
- // TODO Auto-generated method stub
+ public void pushFlowMetrics(DeviceId deviceId, Iterable<FlowRule> flowEntries) {
+ List<FlowRule> storedRules = Lists.newLinkedList(store.getFlowEntries(deviceId));
+ List<FlowRule> switchRules = Lists.newLinkedList(flowEntries);
+ Iterator<FlowRule> switchRulesIterator = switchRules.iterator();
+ List<FlowRule> extraRules = Lists.newLinkedList();
+
+ while (switchRulesIterator.hasNext()) {
+ FlowRule rule = switchRulesIterator.next();
+ if (storedRules.remove(rule)) {
+ // we both have the rule let's update some info then.
+ log.info("rule {} is added. {}", rule.id(), rule.state());
+ flowAdded(rule);
+ } else {
+ // the device a rule the store does not have
+ extraRules.add(rule);
+ }
+ }
+ for (FlowRule rule : storedRules) {
+ // there are rules in the store that aren't on the switch
+ flowMissing(rule);
+ }
+ if (extraRules.size() > 0) {
+ log.warn("Device {} has extra flow rules: {}", deviceId, extraRules);
+ // TODO do something with this.
+ }
+
}
}
diff --git a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowRuleBuilder.java b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowRuleBuilder.java
index ab01ab7..49ee9b9 100644
--- a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowRuleBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowRuleBuilder.java
@@ -10,6 +10,7 @@
import org.onlab.onos.net.flow.DefaultTrafficSelector;
import org.onlab.onos.net.flow.DefaultTrafficTreatment;
import org.onlab.onos.net.flow.FlowRule;
+import org.onlab.onos.net.flow.FlowRule.FlowRuleState;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.flow.criteria.Criteria;
@@ -69,14 +70,14 @@
if (stat != null) {
return new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
buildSelector(), buildTreatment(), stat.getPriority(),
- stat.getDurationNsec() / 1000000, stat.getIdleTimeout(),
+ FlowRuleState.ADDED, stat.getDurationNsec() / 1000000,
stat.getPacketCount().getValue(), stat.getByteCount().getValue(),
(int) (stat.getCookie().getValue() & 0xFFFFFFFF));
} else {
// TODO: revisit potentially.
return new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
buildSelector(), null, removed.getPriority(),
- removed.getDurationNsec() / 1000000, removed.getIdleTimeout(),
+ FlowRuleState.REMOVED, removed.getDurationNsec() / 1000000,
removed.getPacketCount().getValue(), removed.getByteCount().getValue(),
(int) (removed.getCookie().getValue() & 0xFFFFFFFF));
}
diff --git a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
index b11eb0c..7cb4fdf 100644
--- a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
+++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
@@ -10,6 +10,7 @@
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.flow.FlowRule;
import org.onlab.onos.net.flow.FlowRuleProvider;
import org.onlab.onos.net.flow.FlowRuleProviderRegistry;
@@ -154,7 +155,7 @@
entries.add(new FlowRuleBuilder(dpid, reply).build());
}
log.debug("sending flowstats to core {}", entries);
- providerService.pushFlowMetrics(entries);
+ providerService.pushFlowMetrics(DeviceId.deviceId(Dpid.uri(dpid)), entries);
}
}