[SDFAB-1177] Separate ingress and egress UpfCounter
Change-Id: I957754bc3f12d2e8f6d9d5748bb0b8c2b01a924c
(cherry picked from commit db0e125ac2515dbb711efdeebc3948b28e9e392b)
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/upf/UpfCounter.java b/core/api/src/main/java/org/onosproject/net/behaviour/upf/UpfCounter.java
index eb41a04..c395009 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/upf/UpfCounter.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/upf/UpfCounter.java
@@ -16,34 +16,40 @@
package org.onosproject.net.behaviour.upf;
-
import com.google.common.annotations.Beta;
import java.util.Objects;
+import java.util.Optional;
+import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.behaviour.upf.UpfEntityType.COUNTER;
+import static org.onosproject.net.behaviour.upf.UpfEntityType.EGRESS_COUNTER;
+import static org.onosproject.net.behaviour.upf.UpfEntityType.INGRESS_COUNTER;
/**
- * A structure for compactly passing UPF counter values for a given counter ID.
- * Contains four counts: Ingress Packets, Ingress Bytes, Egress Packets, Egress Bytes.
- * UpfCounter can be used ONLY on {@code apply} and {@code readAll} calls in the
- * {@link UpfDevice} interface.
+ * A structure for compactly passing UPF counter (ingress, egress or both) values
+ * for a given counter ID. Contains four counts: Ingress Packets, Ingress Bytes,
+ * Egress Packets, Egress Bytes. UpfCounter can be used ONLY on {@code apply}
+ * and {@code readAll} calls in the {@link UpfDevice} interface.
*/
@Beta
public final class UpfCounter implements UpfEntity {
private final int cellId;
- private final long ingressPkts;
- private final long ingressBytes;
- private final long egressPkts;
- private final long egressBytes;
+ private final Long ingressPkts;
+ private final Long ingressBytes;
+ private final Long egressPkts;
+ private final Long egressBytes;
+ private final UpfEntityType type;
- private UpfCounter(int cellId, long ingressPkts, long ingressBytes,
- long egressPkts, long egressBytes) {
+ private UpfCounter(int cellId, Long ingressPkts, Long ingressBytes,
+ Long egressPkts, Long egressBytes, UpfEntityType type) {
this.cellId = cellId;
this.ingressPkts = ingressPkts;
this.ingressBytes = ingressBytes;
this.egressPkts = egressPkts;
this.egressBytes = egressBytes;
+ this.type = type;
}
public static Builder builder() {
@@ -52,8 +58,19 @@
@Override
public String toString() {
- return String.format("UpfStats(cell_id=%d, ingress=(%dpkts,%dbytes), egress=(%dpkts,%dbytes))",
- cellId, ingressPkts, ingressBytes, egressPkts, egressBytes);
+ switch (this.type) {
+ case COUNTER:
+ return String.format("UpfStats(cell_id=%d, ingress=(%dpkts,%dbytes), egress=(%dpkts,%dbytes))",
+ cellId, ingressPkts, ingressBytes, egressPkts, egressBytes);
+ case INGRESS_COUNTER:
+ return String.format("UpfIngressCounter(cell_id=%d, packets=%d, bytes=%d))",
+ cellId, ingressPkts, ingressBytes);
+ case EGRESS_COUNTER:
+ return String.format("UpfEgressCounter(cell_id=%d, packets=%d, bytes=%d))",
+ cellId, egressPkts, egressBytes);
+ default:
+ throw new IllegalStateException("I should never reach this point!");
+ }
}
@Override
@@ -68,7 +85,7 @@
return false;
}
UpfCounter that = (UpfCounter) object;
- return this.cellId == that.cellId;
+ return this.cellId == that.cellId && this.type == that.type;
}
/**
@@ -80,16 +97,15 @@
*/
public boolean exactlyEquals(UpfCounter that) {
return this.equals(that) &&
- this.ingressPkts == that.ingressPkts &&
- this.ingressBytes == that.ingressBytes &&
- this.egressPkts == that.egressPkts &&
- this.egressBytes == that.egressBytes;
+ (this.ingressPkts == that.ingressPkts || this.ingressPkts.equals(that.ingressPkts)) &&
+ (this.ingressBytes == that.ingressBytes || this.ingressBytes.equals(that.ingressBytes)) &&
+ (this.egressPkts == that.egressPkts || this.egressPkts.equals(that.egressPkts)) &&
+ (this.egressBytes == that.egressBytes || this.egressBytes.equals(that.egressBytes));
}
-
@Override
public int hashCode() {
- return Objects.hash(cellId);
+ return Objects.hash(cellId, type);
}
/**
@@ -103,57 +119,91 @@
/**
* Get the number of packets that hit this counter in the dataplane ingress pipeline.
+ * Return a value only if the counter is of type {@code UpfEntityType.COUNTER}
+ * or {@code UpfEntityType.INGRESS_COUNTER}, otherwise an empty Optional.
*
- * @return ingress packet count
+ * @return ingress packet count or empty if this is of type {@code UpfEntityType.EGRESS_COUNTER}
*/
- public long getIngressPkts() {
- return ingressPkts;
+ public Optional<Long> getIngressPkts() {
+ return Optional.ofNullable(ingressPkts);
}
/**
* Get the number of packets that hit this counter in the dataplane egress pipeline.
+ * Return a value only if the counter is of type {@code UpfEntityType.COUNTER}
+ * or {@code UpfEntityType.EGRESS_COUNTER}, otherwise an empty Optional.
*
- * @return egress packet count
+ * @return egress packet count or empty if this is of type {@code UpfEntityType.INGRESS_COUNTER}
*/
- public long getEgressPkts() {
- return egressPkts;
+ public Optional<Long> getEgressPkts() {
+ return Optional.ofNullable(egressPkts);
}
/**
* Get the number of packet bytes that hit this counter in the dataplane ingress pipeline.
+ * Return value only if the counter is of type {{@code UpfEntityType.COUNTER}
+ * or {@code UpfEntityType.INGRESS_COUNTER}, otherwise an empty Optional.
*
- * @return ingress byte count
+ * @return ingress byte count or empty if this is of type {@code UpfEntityType.EGRESS_COUNTER}
*/
- public long getIngressBytes() {
- return ingressBytes;
+ public Optional<Long> getIngressBytes() {
+ return Optional.ofNullable(ingressBytes);
}
/**
* Get the number of packet bytes that hit this counter in the dataplane egress pipeline.
+ * Return a value only if the counter is of type {@code UpfEntityType.COUNTER}
+ * or {@code UpfEntityType.EGRESS_COUNTER}, otherwise an empty Optional.
*
- * @return egress byte count
+ * @return egress byte count or empty if this is of type {@code UpfEntityType.INGRESS_COUNTER}
*/
- public long getEgressBytes() {
- return egressBytes;
+ public Optional<Long> getEgressBytes() {
+ return Optional.ofNullable(egressBytes);
}
@Override
public UpfEntityType type() {
- return UpfEntityType.COUNTER;
+ return type;
}
+ /**
+ * Sum the content of the given UpfCounter to the counter values contained
+ * in this instance.
+ *
+ * @param that The UpfCounter to sum to this instance
+ * @return a new UpfCounter instance with sum counters.
+ * @throws IllegalArgumentException if the given UpfCounter is not referring
+ * to the same type and id as this
+ */
+ public UpfCounter sum(UpfCounter that) throws IllegalArgumentException {
+ if (!this.equals(that)) {
+ throw new IllegalArgumentException(
+ "The given UpfCounter is not of the same type or refers to a different index");
+ }
+ UpfCounter.Builder builder = UpfCounter.builder().withCellId(this.getCellId());
+ if (this.type.equals(UpfEntityType.COUNTER) || this.type.equals(UpfEntityType.INGRESS_COUNTER)) {
+ builder.setIngress(this.ingressPkts + that.ingressPkts,
+ this.ingressBytes + that.ingressBytes);
+ }
+ if (this.type.equals(UpfEntityType.COUNTER) || this.type.equals(UpfEntityType.EGRESS_COUNTER)) {
+ builder.setEgress(this.egressPkts + that.egressPkts,
+ this.egressBytes + that.egressBytes);
+ }
+ return builder.build();
+ }
+
+ /**
+ * Builder for UpfCounter.
+ */
public static class Builder {
private Integer cellId;
- private long ingressPkts;
- private long ingressBytes;
- private long egressPkts;
- private long egressBytes;
+ private Long ingressPkts;
+ private Long ingressBytes;
+ private Long egressPkts;
+ private Long egressBytes;
+ private UpfEntityType type = COUNTER;
public Builder() {
- this.ingressPkts = 0;
- this.ingressBytes = 0;
- this.egressPkts = 0;
- this.egressBytes = 0;
}
/**
@@ -193,9 +243,51 @@
return this;
}
+ /**
+ * Set the counter as ingress only counter.
+ *
+ * @return This builder
+ */
+ public Builder isIngressCounter() {
+ this.type = INGRESS_COUNTER;
+ return this;
+ }
+
+ /**
+ * Set the counter as egress only counter.
+ *
+ * @return This builder
+ */
+ public Builder isEgressCounter() {
+ this.type = EGRESS_COUNTER;
+ return this;
+ }
+
public UpfCounter build() {
checkNotNull(cellId, "CellID must be provided");
- return new UpfCounter(cellId, ingressPkts, ingressBytes, egressPkts, egressBytes);
+ switch (type) {
+ case INGRESS_COUNTER:
+ checkArgument(this.ingressBytes != null && this.ingressPkts != null,
+ "Ingress counter values must be provided");
+ this.egressBytes = null;
+ this.egressPkts = null;
+ break;
+ case EGRESS_COUNTER:
+ checkArgument(this.egressBytes != null && this.egressPkts != null,
+ "Egress counter values must be provided");
+ this.ingressBytes = null;
+ this.ingressPkts = null;
+ break;
+ case COUNTER:
+ checkArgument(this.ingressBytes != null && this.ingressPkts != null &&
+ this.egressBytes != null && this.egressPkts != null,
+ "Ingress and egress counter values must be provided");
+ break;
+ default:
+ // I should never reach this point
+ throw new IllegalArgumentException("I should never reach this point!");
+ }
+ return new UpfCounter(cellId, ingressPkts, ingressBytes, egressPkts, egressBytes, type);
}
}
}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/upf/UpfDevice.java b/core/api/src/main/java/org/onosproject/net/behaviour/upf/UpfDevice.java
index 2b17421..738d6b6 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/upf/UpfDevice.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/upf/UpfDevice.java
@@ -52,27 +52,31 @@
Collection<? extends UpfEntity> readAll(UpfEntityType entityType) throws UpfProgrammableException;
/**
- * Reads the given UPF counter ID from the UPF-programmable device.
+ * Reads the given UPF counter type and index from the UPF-programmable device.
*
- * @param counterId The counter ID from which to read.
+ * @param counterIdx The counter index from which to read.
+ * @param type {@link UpfEntityType} of UPF counter to read
+ * ({@code COUNTER, INGRESS_COUNTER, EGRESS_COUNTER})
* @return The content of the UPF counter.
* @throws UpfProgrammableException if the counter ID is out of bounds.
*/
- UpfCounter readCounter(int counterId) throws UpfProgrammableException;
+ UpfCounter readCounter(int counterIdx, UpfEntityType type) throws UpfProgrammableException;
/**
- * Reads the UPF counter contents for all indices that are valid on the
- * UPF-programmable device. {@code maxCounterId} parameter is used to limit
- * the number of counters retrieved from the UPF. If the limit given is
+ * Reads the given UPF counter type contents for all indices that are valid
+ * on the UPF-programmable device. {@code maxCounterId} parameter is used to
+ * limit the number of counters retrieved from the UPF. If the limit given is
* larger than the physical limit, the physical limit will be used.
* A limit of -1 removes limitations, and it is equivalent of calling
- * {@link #readAll(UpfEntityType)} passing the {@code COUNTER} {@link UpfEntityType}.
+ * {@link #readAll(UpfEntityType)} passing the given {@link UpfEntityType}.
*
- * @param maxCounterId Maximum counter ID to retrieve from the UPF device.
+ * @param maxCounterIdx Maximum counter index to retrieve from the UPF device.
+ * @param type {@link UpfEntityType} of UPF counter to read
+ * ({@code COUNTER, INGRESS_COUNTER, EGRESS_COUNTER})
* @return A collection of UPF counters for all valid hardware counter cells.
* @throws UpfProgrammableException if the counters are unable to be read.
*/
- Collection<UpfCounter> readCounters(long maxCounterId) throws UpfProgrammableException;
+ Collection<UpfCounter> readCounters(long maxCounterIdx, UpfEntityType type) throws UpfProgrammableException;
/**
* Deletes the given UPF entity from the UPF-programmable device.
@@ -97,6 +101,7 @@
* the UPF-programmable device. For entities that have a direction,returns
* the total amount of entities including both the downlink and the uplink
* directions.
+ *
* @param entityType The type of UPF programmable entities to retrieve the size from.
* @return The total number of supported UPF entities.
* @throws UpfProgrammableException if the operation is not supported on the given UPF entity.
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/upf/UpfEntityType.java b/core/api/src/main/java/org/onosproject/net/behaviour/upf/UpfEntityType.java
index 07890f7..e13a3c8 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/upf/UpfEntityType.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/upf/UpfEntityType.java
@@ -29,6 +29,8 @@
SESSION_DOWNLINK("session_downlink"),
SESSION_UPLINK("session_downlink"),
TUNNEL_PEER("tunnel_peer"),
+ INGRESS_COUNTER("ingress_counter"),
+ EGRESS_COUNTER("egress_counter"),
COUNTER("counter"),
APPLICATION("application"),
SESSION_METER("session_meter"),