ONOS-5475 OFAgent - Handle OFFlowStatsRequest, OFTableDescStatsRequest, OFGroupStatsRequest, OFGroupDescStatsRequest

Change-Id: I67734951a756ea61d8aaf9d520b3101141e3d73c
This commit is contained in:
Claudine Chiu 2017-08-16 10:06:20 -04:00 committed by Yoonseon Han
parent aa279c014e
commit ce8ccc604f
3 changed files with 195 additions and 3 deletions

View File

@ -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<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.
*

View File

@ -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<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 @@ public final class DefaultOFSwitch implements OFSwitch {
//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())

View File

@ -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<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),