ONOS-5475 OFAgent - Handle OFFlowStatsRequest, OFTableDescStatsRequest, OFGroupStatsRequest, OFGroupDescStatsRequest
Change-Id: I67734951a756ea61d8aaf9d520b3101141e3d73c
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchService.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchService.java
index 395f08e..cbed3d9 100644
--- a/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchService.java
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchService.java
@@ -21,6 +21,9 @@
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.PortStatistics;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.TableStatisticsEntry;
+import org.onosproject.net.group.Group;
import java.util.List;
import java.util.Set;
@@ -73,6 +76,33 @@
List<PortStatistics> getPortStatistics(NetworkId networkId, DeviceId deviceId);
/**
+ * Returns all flow entries of the specified device in the specified network.
+ *
+ * @param networkId network id
+ * @param deviceId device id
+ * @return list of flow entries; empty list if none exists for the specified device
+ */
+ List<FlowEntry> getFlowEntries(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Returns all flow table statistics of the specified device in the specified network.
+ *
+ * @param networkId network id
+ * @param deviceId device id
+ * @return list of flow table statistics; empty list if none exists for the specified device
+ */
+ List<TableStatisticsEntry> getFlowTableStatistics(NetworkId networkId, DeviceId deviceId);
+
+ /**
+ * Returns all groups associated with the specified device in the specified network.
+ *
+ * @param networkId network id
+ * @param deviceId device id
+ * @return list of groups; empty list if none exists for the specified device
+ */
+ List<Group> getGroups(NetworkId networkId, DeviceId deviceId);
+
+ /**
* Returns neighbour port of the specified port in the specified network.
*
* @param networkId network id
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFSwitch.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFSwitch.java
index 72a0c2f..3f4f878 100644
--- a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFSwitch.java
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFSwitch.java
@@ -16,28 +16,38 @@
package org.onosproject.ofagent.impl;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
import io.netty.channel.Channel;
import org.onlab.osgi.ServiceDirectory;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
-import org.onosproject.net.device.PortStatistics;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.PortStatistics;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TableStatisticsEntry;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.packet.InboundPacket;
import org.onosproject.ofagent.api.OFSwitch;
import org.onosproject.ofagent.api.OFSwitchCapabilities;
import org.onosproject.ofagent.api.OFSwitchService;
import org.projectfloodlight.openflow.protocol.OFActionType;
import org.projectfloodlight.openflow.protocol.OFBarrierReply;
+import org.projectfloodlight.openflow.protocol.OFBucket;
+import org.projectfloodlight.openflow.protocol.OFBucketCounter;
import org.projectfloodlight.openflow.protocol.OFControllerRole;
import org.projectfloodlight.openflow.protocol.OFEchoReply;
import org.projectfloodlight.openflow.protocol.OFEchoRequest;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
import org.projectfloodlight.openflow.protocol.OFGetConfigReply;
+import org.projectfloodlight.openflow.protocol.OFGroupDescStatsEntry;
+import org.projectfloodlight.openflow.protocol.OFGroupStatsEntry;
+import org.projectfloodlight.openflow.protocol.OFGroupType;
import org.projectfloodlight.openflow.protocol.OFHello;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFMeterFeatures;
@@ -54,14 +64,18 @@
import org.projectfloodlight.openflow.protocol.OFSetConfig;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.OFStatsRequest;
+import org.projectfloodlight.openflow.protocol.OFTableStatsEntry;
import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.protocol.match.Match;
import org.projectfloodlight.openflow.protocol.match.MatchField;
import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFGroup;
import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.TableId;
import org.projectfloodlight.openflow.types.U64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -259,6 +273,76 @@
return ofPortStatsEntry;
}
+ private OFFlowStatsEntry ofFlowStatsEntry(FlowEntry flowEntry) {
+ // TODO get match from flowEntry.selector()
+ Match.Builder matchB = FACTORY.buildMatch();
+ OFActionOutput actionOutput = FACTORY.actions()
+ .buildOutput().build();
+ // TODO get instructions from flowEntry.treatment()
+ OFInstruction instruction = FACTORY.instructions()
+ .applyActions(Collections.singletonList(actionOutput));
+ OFFlowStatsEntry ofFlowStatsEntry = FACTORY.buildFlowStatsEntry()
+ .setMatch(matchB.build())
+ .setInstructions(Collections.singletonList(instruction))
+ .setTableId(TableId.of(flowEntry.tableId()))
+ .setHardTimeout(flowEntry.hardTimeout())
+ .setIdleTimeout(flowEntry.timeout())
+ .setCookie(U64.of(flowEntry.id().value()))
+ .setPriority(flowEntry.priority())
+ .setDurationSec(flowEntry.life())
+ .setPacketCount(U64.of(flowEntry.packets()))
+ .setByteCount(U64.of(flowEntry.bytes()))
+ .build();
+ return ofFlowStatsEntry;
+ }
+
+ private OFTableStatsEntry ofFlowTableStatsEntry(TableStatisticsEntry tableStatisticsEntry) {
+ OFTableStatsEntry ofTableStatsEntry = FACTORY.buildTableStatsEntry()
+ .setTableId(TableId.of(tableStatisticsEntry.tableId()))
+ .setActiveCount(tableStatisticsEntry.activeFlowEntries())
+ .setLookupCount(U64.of(tableStatisticsEntry.packetsLookedup()))
+ .setMatchedCount(U64.of(tableStatisticsEntry.packetsLookedup()))
+ .build();
+ return ofTableStatsEntry;
+ }
+
+ private OFGroupStatsEntry ofGroupStatsEntry(Group group) {
+ List<OFBucketCounter> ofBucketCounters = Lists.newArrayList();
+ group.buckets().buckets().forEach(groupBucket -> {
+ ofBucketCounters.add(FACTORY.bucketCounter(
+ U64.of(groupBucket.packets()), U64.of(groupBucket.bytes())));
+ });
+ OFGroupStatsEntry entry = FACTORY.buildGroupStatsEntry()
+ .setGroup(OFGroup.of(group.id().id()))
+ .setDurationSec(group.life())
+ .setPacketCount(U64.of(group.packets()))
+ .setByteCount(U64.of(group.bytes()))
+ .setRefCount(group.referenceCount())
+ .setBucketStats(ofBucketCounters)
+ .build();
+ return entry;
+ }
+
+ private OFGroupDescStatsEntry ofGroupDescStatsEntry(Group group) {
+ List<OFBucket> ofBuckets = Lists.newArrayList();
+ group.buckets().buckets().forEach(groupBucket -> {
+ ofBuckets.add(FACTORY.buildBucket()
+ .setWeight(groupBucket.weight())
+ .setWatchGroup(OFGroup.of(groupBucket.watchGroup().id()))
+ .setWatchPort(OFPort.of((int) groupBucket.watchPort().toLong()))
+ .build()
+ );
+ });
+ OFGroup ofGroup = OFGroup.of(group.givenGroupId());
+ OFGroupType ofGroupType = OFGroupType.valueOf(group.type().name());
+ OFGroupDescStatsEntry entry = FACTORY.buildGroupDescStatsEntry()
+ .setGroup(ofGroup)
+ .setGroupType(ofGroupType)
+ .setBuckets(ofBuckets)
+ .build();
+ return entry;
+ }
+
@Override
public void processStatsRequest(Channel channel, OFMessage msg) {
if (msg.getType() != OFType.STATS_REQUEST) {
@@ -308,6 +392,54 @@
//TODO add details
.build();
break;
+ case FLOW:
+ List<OFFlowStatsEntry> flowStatsEntries = new ArrayList<>();
+ List<FlowEntry> flowStats = ofSwitchService.getFlowEntries(networkId, deviceId);
+ flowStats.forEach(flowEntry -> {
+ OFFlowStatsEntry ofFlowStatsEntry = ofFlowStatsEntry(flowEntry);
+ flowStatsEntries.add(ofFlowStatsEntry);
+ });
+ ofStatsReply = FACTORY.buildFlowStatsReply()
+ .setEntries(flowStatsEntries)
+ .setXid(msg.getXid())
+ .build();
+ break;
+ case TABLE:
+ List<OFTableStatsEntry> ofTableStatsEntries = new ArrayList<>();
+ List<TableStatisticsEntry> tableStats = ofSwitchService.getFlowTableStatistics(networkId, deviceId);
+ tableStats.forEach(tableStatisticsEntry -> {
+ OFTableStatsEntry ofFlowStatsEntry = ofFlowTableStatsEntry(tableStatisticsEntry);
+ ofTableStatsEntries.add(ofFlowStatsEntry);
+ });
+ ofStatsReply = FACTORY.buildTableStatsReply()
+ .setEntries(ofTableStatsEntries)
+ .setXid(msg.getXid())
+ .build();
+ break;
+ case GROUP:
+ List<Group> groupStats = ofSwitchService.getGroups(networkId, deviceId);
+ List<OFGroupStatsEntry> ofGroupStatsEntries = new ArrayList<>();
+ groupStats.forEach(group -> {
+ OFGroupStatsEntry entry = ofGroupStatsEntry(group);
+ ofGroupStatsEntries.add(entry);
+ });
+ ofStatsReply = FACTORY.buildGroupStatsReply()
+ .setEntries(ofGroupStatsEntries)
+ .setXid(msg.getXid())
+ .build();
+ break;
+ case GROUP_DESC:
+ List<OFGroupDescStatsEntry> ofGroupDescStatsEntries = new ArrayList<>();
+ List<Group> groupStats2 = ofSwitchService.getGroups(networkId, deviceId);
+ groupStats2.forEach(group -> {
+ OFGroupDescStatsEntry entry = ofGroupDescStatsEntry(group);
+ ofGroupDescStatsEntries.add(entry);
+ });
+ ofStatsReply = FACTORY.buildGroupDescStatsReply()
+ .setEntries(ofGroupDescStatsEntries)
+ .setXid(msg.getXid())
+ .build();
+ break;
case DESC:
ofStatsReply = FACTORY.buildDescStatsReply()
.setXid(msg.getXid())
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFSwitchManager.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFSwitchManager.java
index 101e531..69ea60a 100644
--- a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFSwitchManager.java
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFSwitchManager.java
@@ -16,6 +16,7 @@
package org.onosproject.ofagent.impl;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
import io.netty.channel.ChannelOutboundInvoker;
import io.netty.channel.nio.NioEventLoopGroup;
import org.apache.felix.scr.annotations.Activate;
@@ -44,9 +45,13 @@
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.PortStatistics;
+import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleListener;
import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TableStatisticsEntry;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.group.GroupService;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketProcessor;
@@ -65,6 +70,7 @@
import java.net.InetSocketAddress;
import java.net.SocketAddress;
+import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -198,6 +204,30 @@
return null;
}
+ @Override
+ public List<FlowEntry> getFlowEntries(NetworkId networkId, DeviceId deviceId) {
+ FlowRuleService flowRuleService = virtualNetService.get(networkId, FlowRuleService.class);
+ Iterable<FlowEntry> entries = flowRuleService.getFlowEntries(deviceId);
+ return Lists.newArrayList(entries);
+ }
+
+ @Override
+ public List<TableStatisticsEntry> getFlowTableStatistics(NetworkId networkId, DeviceId deviceId) {
+ FlowRuleService flowRuleService = virtualNetService.get(networkId, FlowRuleService.class);
+ Iterable<TableStatisticsEntry> entries = flowRuleService.getFlowTableStatistics(deviceId);
+ if (entries == null) {
+ entries = new ArrayList<>();
+ }
+ return Lists.newArrayList(entries);
+ }
+
+ @Override
+ public List<Group> getGroups(NetworkId networkId, DeviceId deviceId) {
+ GroupService groupService = virtualNetService.get(networkId, GroupService.class);
+ Iterable<Group> entries = groupService.getGroups(deviceId);
+ return Lists.newArrayList(entries);
+ }
+
private void addOFSwitch(NetworkId networkId, DeviceId deviceId) {
OFSwitch ofSwitch = DefaultOFSwitch.of(
dpidWithDeviceId(deviceId),