use of org.onosproject.net.pi.runtime.PiCounterCell in project onos by opennetworkinglab.
the class PortStatisticsDiscoveryImpl method discoverPortStatistics.
@Override
public Collection<PortStatistics> discoverPortStatistics() {
DeviceService deviceService = this.handler().get(DeviceService.class);
DeviceId deviceId = this.data().deviceId();
PiPipeconfService piPipeconfService = handler().get(PiPipeconfService.class);
if (!piPipeconfService.ofDevice(deviceId).isPresent() || !piPipeconfService.getPipeconf(piPipeconfService.ofDevice(deviceId).get()).isPresent()) {
log.warn("Unable to get the pipeconf of {}, aborting operation", deviceId);
return Collections.emptyList();
}
PiPipeconf pipeconf = piPipeconfService.getPipeconf(piPipeconfService.ofDevice(deviceId).get()).get();
P4RuntimeController controller = handler().get(P4RuntimeController.class);
P4RuntimeClient client = controller.get(deviceId);
if (client == null) {
log.warn("Unable to find client for {}, aborting operation", deviceId);
return Collections.emptyList();
}
Map<Long, DefaultPortStatistics.Builder> portStatBuilders = Maps.newHashMap();
deviceService.getPorts(deviceId).forEach(p -> portStatBuilders.put(p.number().toLong(), DefaultPortStatistics.builder().setPort(p.number()).setDeviceId(deviceId).setDurationSec(getDuration(p.number()))));
Set<PiCounterCellId> counterCellIds = Sets.newHashSet();
portStatBuilders.keySet().forEach(p -> {
// Counter cell/index = port number.
counterCellIds.add(PiCounterCellId.ofIndirect(ingressCounterId(), p));
counterCellIds.add(PiCounterCellId.ofIndirect(egressCounterId(), p));
});
Set<PiCounterCellHandle> counterCellHandles = counterCellIds.stream().map(id -> PiCounterCellHandle.of(deviceId, id)).collect(Collectors.toSet());
// Query the device.
Collection<PiCounterCell> counterEntryResponse = client.read(DEFAULT_P4_DEVICE_ID, pipeconf).handles(counterCellHandles).submitSync().all(PiCounterCell.class);
counterEntryResponse.forEach(counterCell -> {
if (counterCell.cellId().counterType() != INDIRECT) {
log.warn("Invalid counter data type {}, skipping", counterCell.cellId().counterType());
return;
}
PiCounterCellId indCellId = counterCell.cellId();
if (!portStatBuilders.containsKey(indCellId.index())) {
log.warn("Unrecognized counter index {}, skipping", counterCell);
return;
}
DefaultPortStatistics.Builder statsBuilder = portStatBuilders.get(indCellId.index());
if (counterCell.cellId().counterId().equals(ingressCounterId())) {
statsBuilder.setPacketsReceived(counterCell.data().packets());
statsBuilder.setBytesReceived(counterCell.data().bytes());
} else if (counterCell.cellId().counterId().equals(egressCounterId())) {
statsBuilder.setPacketsSent(counterCell.data().packets());
statsBuilder.setBytesSent(counterCell.data().bytes());
} else {
log.warn("Unrecognized counter ID {}, skipping", counterCell);
}
});
return portStatBuilders.values().stream().map(DefaultPortStatistics.Builder::build).collect(Collectors.toList());
}
use of org.onosproject.net.pi.runtime.PiCounterCell in project up4 by omec-project.
the class Up4NorthComponentTest method readCounterTest.
private void readCounterTest(PiCounterId counterId, long expectedPackets, long expectedBytes) {
MockStreamObserver<P4RuntimeOuterClass.ReadResponse> responseObserver = new MockStreamObserver<>();
int cellIndex = 1;
PiCounterCell requestedCell = new PiCounterCell(PiCounterCellId.ofIndirect(counterId, cellIndex), 0, 0);
P4RuntimeOuterClass.Entity entity;
try {
entity = Codecs.CODECS.entity().encode(requestedCell, null, pipeconf);
} catch (CodecException e) {
fail("Unable to encode counter cell to p4runtime entity.");
return;
}
P4RuntimeOuterClass.ReadRequest request = P4RuntimeOuterClass.ReadRequest.newBuilder().addEntities(entity).setDeviceId(NorthTestConstants.P4RUNTIME_DEVICE_ID).build();
up4NorthService.read(request, responseObserver);
var response = responseObserver.lastResponse();
PiCounterCell expectedCell = new PiCounterCell(PiCounterCellId.ofIndirect(counterId, cellIndex), expectedPackets, expectedBytes);
P4RuntimeOuterClass.Entity expectedEntity;
try {
expectedEntity = Codecs.CODECS.entity().encode(expectedCell, null, pipeconf);
} catch (CodecException e) {
fail("Unable to encode counter cell to p4runtime entity.");
return;
}
assertThat(response.getEntitiesCount(), equalTo(1));
assertThat(response.getEntitiesList().get(0), equalTo(expectedEntity));
}
use of org.onosproject.net.pi.runtime.PiCounterCell in project up4 by omec-project.
the class Up4NorthComponentTest method entityToCounterCell.
private PiCounterCell entityToCounterCell(P4RuntimeOuterClass.Entity entity) {
PiEntity responsePiEntity;
try {
responsePiEntity = Codecs.CODECS.entity().decode(entity, null, pipeconf);
} catch (CodecException e) {
fail("Unable to decode p4runtime entity from read response.");
return null;
}
assertThat(responsePiEntity.piEntityType(), equalTo(PiEntityType.COUNTER_CELL));
return (PiCounterCell) responsePiEntity;
}
use of org.onosproject.net.pi.runtime.PiCounterCell in project onos by opennetworkinglab.
the class PortStatisticsDiscoveryImpl method discoverPortStatistics.
@Override
public Collection<PortStatistics> discoverPortStatistics() {
DeviceService deviceService = this.handler().get(DeviceService.class);
DeviceId deviceId = this.data().deviceId();
// Get a client for this device.
P4RuntimeController controller = handler().get(P4RuntimeController.class);
P4RuntimeClient client = controller.get(deviceId);
if (client == null) {
log.warn("Unable to find client for {}, aborting operation", deviceId);
return Collections.emptyList();
}
// Get the pipeconf of this device.
PiPipeconfService piPipeconfService = handler().get(PiPipeconfService.class);
if (!piPipeconfService.ofDevice(deviceId).isPresent() || !piPipeconfService.getPipeconf(piPipeconfService.ofDevice(deviceId).get()).isPresent()) {
log.warn("Unable to get the pipeconf of {}, aborting operation", deviceId);
return Collections.emptyList();
}
PiPipeconf pipeconf = piPipeconfService.getPipeconf(piPipeconfService.ofDevice(deviceId).get()).get();
// Prepare PortStatistics objects to return, one per port of this device.
Map<Long, DefaultPortStatistics.Builder> portStatBuilders = Maps.newHashMap();
deviceService.getPorts(deviceId).forEach(p -> portStatBuilders.put(p.number().toLong(), DefaultPortStatistics.builder().setPort(p.number()).setDeviceId(deviceId)));
// Generate the counter cell IDs.
Set<PiCounterCellId> counterCellIds = Sets.newHashSet();
portStatBuilders.keySet().forEach(p -> {
// Counter cell/index = port number.
counterCellIds.add(PiCounterCellId.ofIndirect(INGRESS_COUNTER_ID, p));
counterCellIds.add(PiCounterCellId.ofIndirect(EGRESS_COUNTER_ID, p));
});
Set<PiCounterCellHandle> counterCellHandles = counterCellIds.stream().map(id -> PiCounterCellHandle.of(deviceId, id)).collect(Collectors.toSet());
// Query the device.
Collection<PiCounterCell> counterEntryResponse = client.read(DEFAULT_P4_DEVICE_ID, pipeconf).handles(counterCellHandles).submitSync().all(PiCounterCell.class);
// Process response.
counterEntryResponse.forEach(counterCell -> {
if (counterCell.cellId().counterType() != INDIRECT) {
log.warn("Invalid counter data type {}, skipping", counterCell.cellId().counterType());
return;
}
if (!portStatBuilders.containsKey(counterCell.cellId().index())) {
log.warn("Unrecognized counter index {}, skipping", counterCell);
return;
}
DefaultPortStatistics.Builder statsBuilder = portStatBuilders.get(counterCell.cellId().index());
if (counterCell.cellId().counterId().equals(INGRESS_COUNTER_ID)) {
statsBuilder.setPacketsReceived(counterCell.data().packets());
statsBuilder.setBytesReceived(counterCell.data().bytes());
} else if (counterCell.cellId().counterId().equals(EGRESS_COUNTER_ID)) {
statsBuilder.setPacketsSent(counterCell.data().packets());
statsBuilder.setBytesSent(counterCell.data().bytes());
} else {
log.warn("Unrecognized counter ID {}, skipping", counterCell);
}
});
return portStatBuilders.values().stream().map(DefaultPortStatistics.Builder::build).collect(Collectors.toList());
}
use of org.onosproject.net.pi.runtime.PiCounterCell in project up4 by omec-project.
the class Up4NorthComponent method readCountersAndTranslate.
/**
* Read the all p4 counter cell requested by the message, and translate them to p4runtime
* entities for crafting a p4runtime read response.
*
* @param message a p4runtime CounterEntry message from a read request
* @return the requested counter cells' contents, as a list of p4runtime entities
* @throws StatusException if the counter index is out of range
*/
private List<P4RuntimeOuterClass.Entity> readCountersAndTranslate(P4RuntimeOuterClass.CounterEntry message) throws StatusException {
ArrayList<PiCounterCell> responseCells = new ArrayList<>();
Integer index = null;
// FYI a counter read message with no index corresponds to a wildcard read of all indices
if (message.hasIndex()) {
index = (int) message.getIndex().getIndex();
}
String counterName = null;
PiCounterId piCounterId = null;
int counterId = message.getCounterId();
// FYI a counterId of 0 corresponds to a wildcard read of all counters
if (counterId != 0) {
try {
counterName = PipeconfHelper.getP4InfoBrowser(pipeconf).counters().getById(message.getCounterId()).getPreamble().getName();
piCounterId = PiCounterId.of(counterName);
} catch (P4InfoBrowser.NotFoundException e) {
log.warn("Unable to find UP4 counter with ID {}", counterId);
throw INVALID_ARGUMENT.withDescription("Invalid UP4 counter identifier.").asException();
}
}
// cell was requested.
if (counterName != null && index != null) {
// A single counter cell was requested
UpfCounter ctrValues;
try {
ctrValues = up4Service.readCounter(index);
} catch (UpfProgrammableException e) {
throw INVALID_ARGUMENT.withDescription(e.getMessage()).asException();
}
long pkts;
long bytes;
if (piCounterId.equals(PRE_QOS_PIPE_PRE_QOS_COUNTER)) {
pkts = ctrValues.getIngressPkts();
bytes = ctrValues.getIngressBytes();
} else if (piCounterId.equals(POST_QOS_PIPE_POST_QOS_COUNTER)) {
pkts = ctrValues.getEgressPkts();
bytes = ctrValues.getEgressBytes();
} else {
log.warn("Received read request for unknown counter {}", piCounterId);
throw INVALID_ARGUMENT.withDescription("Invalid UP4 counter identifier.").asException();
}
responseCells.add(new PiCounterCell(PiCounterCellId.ofIndirect(piCounterId, index), pkts, bytes));
} else {
// All cells were requested, either for a specific counter or all counters
// FIXME: only read the counter that was requested, instead of both ingress and egress unconditionally
Collection<UpfCounter> allStats;
try {
allStats = up4Service.readCounters(-1);
} catch (UpfProgrammableException e) {
throw io.grpc.Status.UNKNOWN.withDescription(e.getMessage()).asException();
}
for (UpfCounter stat : allStats) {
if (piCounterId == null || piCounterId.equals(PRE_QOS_PIPE_PRE_QOS_COUNTER)) {
// If all counters were requested, or just the ingress one
responseCells.add(new PiCounterCell(PiCounterCellId.ofIndirect(PRE_QOS_PIPE_PRE_QOS_COUNTER, stat.getCellId()), stat.getIngressPkts(), stat.getIngressBytes()));
}
if (piCounterId == null || piCounterId.equals(POST_QOS_PIPE_POST_QOS_COUNTER)) {
// If all counters were requested, or just the egress one
responseCells.add(new PiCounterCell(PiCounterCellId.ofIndirect(POST_QOS_PIPE_POST_QOS_COUNTER, stat.getCellId()), stat.getEgressPkts(), stat.getEgressBytes()));
}
}
}
List<P4RuntimeOuterClass.Entity> responseEntities = new ArrayList<>();
for (PiCounterCell cell : responseCells) {
try {
responseEntities.add(Codecs.CODECS.entity().encode(cell, null, pipeconf));
log.trace("Encoded response to counter read request for counter {} and index {}", cell.cellId().counterId(), cell.cellId().index());
} catch (CodecException e) {
log.error("Unable to encode counter cell into a p4runtime entity: {}", e.getMessage());
throw io.grpc.Status.INTERNAL.withDescription("Unable to encode counter cell into a p4runtime entity.").asException();
}
}
log.debug("Encoded response to counter read request for {} cells", responseEntities.size());
return responseEntities;
}
Aggregations