Inspecting clone sessions on a device
I want to: read the clone sessions configured on the device's packet replication engine — typically used for traffic mirroring or telemetry — decode whether each session truncates the cloned payload, and inspect the per-session class of service.
The pattern
import io.github.zhh2001.jp4.P4Switch;
import io.github.zhh2001.jp4.entity.CloneSessionEntry;
import io.github.zhh2001.jp4.entity.Replica;
import java.math.BigInteger;
import java.util.List;
try (P4Switch sw = P4Switch.connectAsPrimary("127.0.0.1:50051")
.bindPipeline(p4info, deviceConfig)) {
List<CloneSessionEntry> sessions = sw.readCloneSession().all();
for (CloneSessionEntry s : sessions) {
String truncation = s.packetLengthBytes() == 0
? "no truncation (full payload)"
: s.packetLengthBytes() + " bytes (truncated)";
System.out.printf("session %d: replicas=%d cos=%d truncation=%s%n",
s.sessionId(),
s.replicas().size(),
s.classOfService(),
truncation);
for (Replica r : s.replicas()) {
String portStr = r.port() == null
? "<unset>"
: String.valueOf(new BigInteger(1, r.port().toByteArray()).intValueExact());
System.out.printf(" replica port=%s instance=%d%n", portStr, r.instance());
}
}
// Read one specific session.
sw.readCloneSession()
.sessionId(42L)
.one()
.ifPresent(s -> System.out.printf(
"session 42: cos=%d packetLen=%d%n",
s.classOfService(), s.packetLengthBytes()));
// Client-side filter: only sessions that truncate.
List<CloneSessionEntry> truncating = sw.readCloneSession()
.where(s -> s.packetLengthBytes() > 0)
.all();
}Walkthrough
sw.readCloneSession()returns aCloneSessionReadQuery. LikereadMulticastGroup, no P4 name argument — clone sessions are program-agnostic, addressed by controller-assignedsessionId.packetLengthBytesencodes the truncation behavior in one int.0means "do not truncate" — every clone carries the original payload in full.- A positive value means "truncate cloned payload to this many bytes" — the device drops any trailing payload beyond the limit.
- The field is mapped to a Java
int(notlong) because the proto declares it asint32and the truncation length is naturally signed-range; negative values are spec-disallowed.
classOfServiceis widened from the proto'suint32tolong— the same widening convention assessionId,groupId,memberId, andmulticastGroupId. The wire range is fully preserved.sessionId(long)is the server-side filter. Populates the wiresession_idfield; the device returns only the matching session.where(Predicate<? super CloneSessionEntry>)is the client-side filter, applied after fetch.
Writing today — what the typed API doesn't yet surface
jp4 v1.5 exposes the read side. To create or modify a clone session on the device today, construct a raw P4Runtime WriteRequest through the generated protobuf classes and send it through the gRPC channel directly:
import p4.v1.P4RuntimeOuterClass.WriteRequest;
import p4.v1.P4RuntimeOuterClass.Update;
import p4.v1.P4RuntimeOuterClass.Entity;
import p4.v1.P4RuntimeOuterClass.PacketReplicationEngineEntry;
import p4.v1.P4RuntimeOuterClass.CloneSessionEntry;
// ... build the proto types directly, then send via the underlying P4RuntimeBlockingStub ...The full pattern lives in the project's integration test fixture: PacketReplicationEngineIntegrationTest.seedCloneSession shows the verbatim raw-proto write sequence used to set up device state for the v1.5 read tests.
This recipe covers the inspection workflow, which is what the typed jp4 API exposes today.
See also
- P4Runtime spec mapping — how
readCloneSessionmaps to the wireEntity.packet_replication_engine_entry.clone_session_entry. port_kindidiom —Replica.portnullability applies to clone-session replicas just as it does to multicast-group replicas.- v1.4 → v1.5 migration guide — the surface introduction.
- Inspecting multicast group state — sister recipe with the same shape against the multicast-group entity.