Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SDFAB-1178] Allow and write in/e-gress counter separately #519

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.tuple.Pair;
import org.glassfish.jersey.internal.guava.Sets;
daniele-moro marked this conversation as resolved.
Show resolved Hide resolved
import org.onlab.packet.Ip4Prefix;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
Expand Down Expand Up @@ -46,9 +47,12 @@
import org.onosproject.net.pi.model.PiTableId;
import org.onosproject.net.pi.model.PiTableModel;
import org.onosproject.net.pi.runtime.PiCounterCell;
import org.onosproject.net.pi.runtime.PiCounterCellData;
import org.onosproject.net.pi.runtime.PiCounterCellHandle;
import org.onosproject.net.pi.runtime.PiCounterCellId;
import org.onosproject.net.pi.runtime.PiEntity;
import org.onosproject.net.pi.runtime.PiMeterCellId;
import org.onosproject.p4runtime.api.P4RuntimeWriteClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.stratumproject.fabric.tna.Constants;
Expand All @@ -67,6 +71,7 @@
import java.util.stream.Collectors;

import static java.lang.String.format;
import static org.onosproject.net.behaviour.upf.UpfProgrammableException.Type.UNSUPPORTED_OPERATION;
import static org.onosproject.net.pi.model.PiCounterType.INDIRECT;
import static org.stratumproject.fabric.tna.behaviour.P4InfoConstants.FABRIC_EGRESS_UPF_EG_TUNNEL_PEERS;
import static org.stratumproject.fabric.tna.behaviour.P4InfoConstants.FABRIC_EGRESS_UPF_GTPU_ENCAP;
Expand Down Expand Up @@ -101,6 +106,9 @@ public class FabricUpfProgrammable extends AbstractP4RuntimeHandlerBehaviour
private static final int DEFAULT_PRIORITY = 128;
private static final long DEFAULT_P4_DEVICE_ID = 1;

private static final ImmutableSet<UpfEntityType> COUNTER_TYPES =
ImmutableSet.of(UpfEntityType.COUNTER, UpfEntityType.INGRESS_COUNTER, UpfEntityType.EGRESS_COUNTER);

protected FlowRuleService flowRuleService;
protected MeterService meterService;
protected PacketService packetService;
Expand Down Expand Up @@ -259,7 +267,7 @@ private boolean computeHardwareResourceSizes() {
long sessionMeterSize = 0;
long appMeterSize = 0;
long sliceMeterSize = 0;
for (PiMeterModel piMeter: pipeconf.pipelineModel().meters()) {
for (PiMeterModel piMeter : pipeconf.pipelineModel().meters()) {
if (piMeter.id().equals(FABRIC_INGRESS_UPF_SESSION_METER)) {
sessionMeterSize = piMeter.size();
} else if (piMeter.id().equals(FABRIC_INGRESS_UPF_APP_METER)) {
Expand Down Expand Up @@ -432,7 +440,11 @@ public Collection<? extends UpfEntity> readAll(UpfEntityType entityType)
case TUNNEL_PEER:
return getGtpTunnelPeers();
case COUNTER:
return readCounters(-1);
return readCounters(-1, UpfEntityType.COUNTER);
case INGRESS_COUNTER:
return readCounters(-1, UpfEntityType.INGRESS_COUNTER);
case EGRESS_COUNTER:
return readCounters(-1, UpfEntityType.EGRESS_COUNTER);
case APPLICATION:
return getUpfApplication();
case SESSION_METER:
Expand Down Expand Up @@ -547,8 +559,42 @@ private Collection<UpfEntity> getUpfTerminationsDownlink() throws UpfProgrammabl
return upfTerminations;
}

private void applyUpfCounter(UpfCounter upfCounter) throws UpfProgrammableException {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be updated when we'll have the counter subsystem in ONOS

final List<PiEntity> counterRequests = Lists.newArrayList();
if (isIngressCounter(upfCounter.type())) {
if (upfCounter.getIngressPkts().isEmpty() || upfCounter.getIngressBytes().isEmpty()) {
throw new UpfProgrammableException("INGRESS counter without ingress packets or bytes!");
}
counterRequests.add(new PiCounterCell(
PiCounterCellId.ofIndirect(FABRIC_INGRESS_UPF_TERMINATIONS_COUNTER, upfCounter.getCellId()),
new PiCounterCellData(upfCounter.getIngressPkts().get(), upfCounter.getIngressBytes().get()))
);
}
if (isEgressCounter(upfCounter.type())) {
if (upfCounter.getEgressPkts().isEmpty() || upfCounter.getEgressBytes().isEmpty()) {
throw new UpfProgrammableException("INGRESS counter without ingress packets or bytes!");
daniele-moro marked this conversation as resolved.
Show resolved Hide resolved
}
counterRequests.add(new PiCounterCell(
PiCounterCellId.ofIndirect(FABRIC_EGRESS_UPF_TERMINATIONS_COUNTER, upfCounter.getCellId()),
new PiCounterCellData(upfCounter.getEgressPkts().get(), upfCounter.getEgressBytes().get()))
);
}
// Write on the device in sync mode.
P4RuntimeWriteClient.WriteResponse writeResponse = client.write(
DEFAULT_P4_DEVICE_ID, pipeconf)
.modify(counterRequests)
.submitSync();
if (!writeResponse.failed().isEmpty()) {
writeResponse.failed().stream().filter(counterEntryResp -> !counterEntryResp.isSuccess())
.forEach(counterEntryResp -> log.error("A counter was not modified correctly: {}",
counterEntryResp.explanation()));
throw new UpfProgrammableException("Failed to modify counters");
}
}

@Override
public Collection<UpfCounter> readCounters(long maxCounterId) {
public Collection<UpfCounter> readCounters(long maxCounterId, UpfEntityType type) throws UpfProgrammableException {
assertCounterType(type);
if (!setupBehaviour("readCounters()")) {
return null;
}
Expand All @@ -565,14 +611,17 @@ public Collection<UpfCounter> readCounters(long maxCounterId) {
}

// Generate the counter cell IDs.
Set<PiCounterId> counterIds = ImmutableSet.of(
FABRIC_INGRESS_UPF_TERMINATIONS_COUNTER,
FABRIC_EGRESS_UPF_TERMINATIONS_COUNTER
);
Set<PiCounterId> counterIds = Sets.newHashSet();
if (isIngressCounter(type)) {
counterIds.add(FABRIC_INGRESS_UPF_TERMINATIONS_COUNTER);
}
if (isEgressCounter(type)) {
counterIds.add(FABRIC_EGRESS_UPF_TERMINATIONS_COUNTER);
}

// Query the device.
Collection<PiCounterCell> counterEntryResponse = client.read(
DEFAULT_P4_DEVICE_ID, pipeconf)
DEFAULT_P4_DEVICE_ID, pipeconf)
.counterCells(counterIds)
.submitSync()
.all(PiCounterCell.class);
Expand Down Expand Up @@ -645,7 +694,8 @@ public long tableSize(UpfEntityType entityType) throws UpfProgrammableException
}

@Override
public UpfCounter readCounter(int cellId) throws UpfProgrammableException {
public UpfCounter readCounter(int cellId, UpfEntityType type) throws UpfProgrammableException {
assertCounterType(type);
if (!setupBehaviour("readCounter()")) {
return null;
}
Expand All @@ -656,11 +706,19 @@ public UpfCounter readCounter(int cellId) throws UpfProgrammableException {
UpfCounter.Builder stats = UpfCounter.builder().withCellId(cellId);

// Make list of cell handles we want to read.
List<PiCounterCellHandle> counterCellHandles = List.of(
PiCounterCellHandle.of(deviceId,
PiCounterCellId.ofIndirect(FABRIC_INGRESS_UPF_TERMINATIONS_COUNTER, cellId)),
PiCounterCellHandle.of(deviceId,
PiCounterCellId.ofIndirect(FABRIC_EGRESS_UPF_TERMINATIONS_COUNTER, cellId)));
List<PiCounterCellHandle> counterCellHandles = Lists.newArrayList();
if (isIngressCounter(type)) {
counterCellHandles.add(PiCounterCellHandle.of(
deviceId,
daniele-moro marked this conversation as resolved.
Show resolved Hide resolved
PiCounterCellId.ofIndirect(FABRIC_INGRESS_UPF_TERMINATIONS_COUNTER, cellId)
));
}
if (isEgressCounter(type)) {
counterCellHandles.add(PiCounterCellHandle.of(
deviceId,
PiCounterCellId.ofIndirect(FABRIC_EGRESS_UPF_TERMINATIONS_COUNTER, cellId)
));
}

// Query the device.
Collection<PiCounterCell> counterEntryResponse = client.read(
Expand Down Expand Up @@ -717,12 +775,16 @@ public void apply(UpfEntity entity) throws UpfProgrammableException {
case APPLICATION:
addUpfApplication((UpfApplication) entity);
break;
case COUNTER:
case INGRESS_COUNTER:
case EGRESS_COUNTER:
applyUpfCounter((UpfCounter) entity);
break;
case SESSION_METER:
case APPLICATION_METER:
case SLICE_METER:
applyUpfMeter((UpfMeter) entity);
break;
case COUNTER:
default:
throw new UpfProgrammableException(format("Adding entity type %s not supported.",
entity.type().humanReadableName()));
Expand Down Expand Up @@ -854,8 +916,8 @@ public void delete(UpfEntity entity) throws UpfProgrammableException {
case SESSION_METER:
case APPLICATION_METER:
case SLICE_METER:
// Meter cannot be deleted, only modified.
case COUNTER:
// Entities cannot be deleted, only modified.
default:
throw new UpfProgrammableException(format("Deleting entity type %s not supported.",
entity.type().humanReadableName()));
Expand All @@ -866,6 +928,7 @@ private boolean removeEntry(PiCriterion match, PiTableId tableId, boolean failSi
throws UpfProgrammableException {
return removeEntry(match, tableId, failSilent, DEFAULT_PRIORITY);
}

private boolean removeEntry(PiCriterion match, PiTableId tableId, boolean failSilent, int priority)
throws UpfProgrammableException {
return removeEntries(Lists.newArrayList(Pair.of(tableId, match)), failSilent, priority);
Expand Down Expand Up @@ -1034,4 +1097,20 @@ private void assertTrafficClass(int sliceId, int tc) throws UpfProgrammableExcep
));
}
}

private void assertCounterType(UpfEntityType type) throws UpfProgrammableException {
if (!COUNTER_TYPES.contains(type)) {
throw new UpfProgrammableException(
String.format("Unsupported counter type (%s)!", type.toString()),
UNSUPPORTED_OPERATION
);
}
}

private boolean isIngressCounter(UpfEntityType type) {
return type.equals(UpfEntityType.COUNTER) || type.equals(UpfEntityType.INGRESS_COUNTER);
}
daniele-moro marked this conversation as resolved.
Show resolved Hide resolved
private boolean isEgressCounter(UpfEntityType type) {
return type.equals(UpfEntityType.COUNTER) || type.equals(UpfEntityType.EGRESS_COUNTER);
}
}
Loading