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 395f08ee0f..cbed3d9b7c 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.DeviceId; 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; @@ -72,6 +75,33 @@ public interface OFSwitchService { */ List 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 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 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 getGroups(NetworkId networkId, DeviceId deviceId); + /** * Returns neighbour port of the specified port in the specified network. * 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 72a0c2fb47..3f4f878ef8 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.OFRoleRequest; 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 @@ public final class DefaultOFSwitch implements OFSwitch { 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 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 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 @@ public final class DefaultOFSwitch implements OFSwitch { //TODO add details .build(); break; + case FLOW: + List flowStatsEntries = new ArrayList<>(); + List 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 ofTableStatsEntries = new ArrayList<>(); + List 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 groupStats = ofSwitchService.getGroups(networkId, deviceId); + List 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 ofGroupDescStatsEntries = new ArrayList<>(); + List 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 101e531a1e..69ea60aac5 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.DeviceEvent; 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 org.slf4j.LoggerFactory; 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 @@ public class OFSwitchManager implements OFSwitchService { return null; } + @Override + public List getFlowEntries(NetworkId networkId, DeviceId deviceId) { + FlowRuleService flowRuleService = virtualNetService.get(networkId, FlowRuleService.class); + Iterable entries = flowRuleService.getFlowEntries(deviceId); + return Lists.newArrayList(entries); + } + + @Override + public List getFlowTableStatistics(NetworkId networkId, DeviceId deviceId) { + FlowRuleService flowRuleService = virtualNetService.get(networkId, FlowRuleService.class); + Iterable entries = flowRuleService.getFlowTableStatistics(deviceId); + if (entries == null) { + entries = new ArrayList<>(); + } + return Lists.newArrayList(entries); + } + + @Override + public List getGroups(NetworkId networkId, DeviceId deviceId) { + GroupService groupService = virtualNetService.get(networkId, GroupService.class); + Iterable entries = groupService.getGroups(deviceId); + return Lists.newArrayList(entries); + } + private void addOFSwitch(NetworkId networkId, DeviceId deviceId) { OFSwitch ofSwitch = DefaultOFSwitch.of( dpidWithDeviceId(deviceId),