ONOS-7066 ONOS-7067 PI abstractions refactoring and P4Info model parser
Includes changes previously reviewed in #15607, #15877, and #15955.
Change-Id: Ie2ff62e415f2099832ebfe05961a879b7b188fc3
diff --git a/apps/p4-tutorial/pipeconf/BUCK b/apps/p4-tutorial/pipeconf/BUCK
index 038736f..6bdb389 100644
--- a/apps/p4-tutorial/pipeconf/BUCK
+++ b/apps/p4-tutorial/pipeconf/BUCK
@@ -1,7 +1,7 @@
COMPILE_DEPS = [
'//lib:CORE_DEPS',
'//lib:minimal-json',
- '//incubator/bmv2/model:onos-incubator-bmv2-model',
+ '//protocols/p4runtime/model:onos-protocols-p4runtime-model',
'//drivers/default:onos-drivers-default',
'//protocols/p4runtime/api:onos-protocols-p4runtime-api',
]
@@ -12,8 +12,6 @@
BUNDLES = [
'//apps/p4-tutorial/pipeconf:onos-apps-p4-tutorial-pipeconf',
- '//drivers/default:onos-drivers-default',
- '//incubator/bmv2/model:onos-incubator-bmv2-model',
]
onos_app (
diff --git a/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PipeconfFactory.java b/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PipeconfFactory.java
index b284eaa..79aa274 100644
--- a/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PipeconfFactory.java
+++ b/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PipeconfFactory.java
@@ -21,7 +21,6 @@
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onosproject.bmv2.model.Bmv2PipelineModelParser;
import org.onosproject.driver.pipeline.DefaultSingleTablePipeline;
import org.onosproject.net.behaviour.Pipeliner;
import org.onosproject.net.device.PortStatisticsDiscovery;
@@ -31,6 +30,8 @@
import org.onosproject.net.pi.model.PiPipelineInterpreter;
import org.onosproject.net.pi.model.PiPipelineModel;
import org.onosproject.net.pi.runtime.PiPipeconfService;
+import org.onosproject.p4runtime.model.P4InfoParser;
+import org.onosproject.p4runtime.model.P4InfoParserException;
import java.net.URL;
@@ -46,18 +47,6 @@
public static final PiPipeconfId PIPECONF_ID = new PiPipeconfId("p4-tutorial-pipeconf");
private static final URL P4INFO_URL = PipeconfFactory.class.getResource("/main.p4info");
private static final URL BMV2_JSON_URL = PipeconfFactory.class.getResource("/main.json");
- private static final PiPipelineModel PIPELINE_MODEL = Bmv2PipelineModelParser.parse(BMV2_JSON_URL);
-
- private static final PiPipeconf PIPECONF = DefaultPiPipeconf.builder()
- .withId(PIPECONF_ID)
- .withPipelineModel(PIPELINE_MODEL)
- .addBehaviour(PiPipelineInterpreter.class, PipelineInterpreterImpl.class)
- .addBehaviour(PortStatisticsDiscovery.class, PortStatisticsDiscoveryImpl.class)
- // Since main.p4 defines only 1 table, we re-use the existing single-table pipeliner.
- .addBehaviour(Pipeliner.class, DefaultSingleTablePipeline.class)
- .addExtension(P4_INFO_TEXT, P4INFO_URL)
- .addExtension(BMV2_JSON, BMV2_JSON_URL)
- .build();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private PiPipeconfService piPipeconfService;
@@ -65,11 +54,31 @@
@Activate
public void activate() {
// Registers the pipeconf at component activation.
- piPipeconfService.register(PIPECONF);
+ piPipeconfService.register(buildPipeconf());
}
@Deactivate
public void deactivate() {
- piPipeconfService.remove(PIPECONF.id());
+ piPipeconfService.remove(PIPECONF_ID);
+ }
+
+ private PiPipeconf buildPipeconf() {
+ final PiPipelineModel pipelineModel;
+ try {
+ pipelineModel = P4InfoParser.parse(P4INFO_URL);
+ } catch (P4InfoParserException e) {
+ throw new RuntimeException(e);
+ }
+
+ return DefaultPiPipeconf.builder()
+ .withId(PIPECONF_ID)
+ .withPipelineModel(pipelineModel)
+ .addBehaviour(PiPipelineInterpreter.class, PipelineInterpreterImpl.class)
+ .addBehaviour(PortStatisticsDiscovery.class, PortStatisticsDiscoveryImpl.class)
+ // Since main.p4 defines only 1 table, we re-use the existing single-table pipeliner.
+ .addBehaviour(Pipeliner.class, DefaultSingleTablePipeline.class)
+ .addExtension(P4_INFO_TEXT, P4INFO_URL)
+ .addExtension(BMV2_JSON, BMV2_JSON_URL)
+ .build();
}
}
diff --git a/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PipelineInterpreterImpl.java b/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PipelineInterpreterImpl.java
index 4c9e5f3..9147de3 100644
--- a/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PipelineInterpreterImpl.java
+++ b/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PipelineInterpreterImpl.java
@@ -23,7 +23,6 @@
import org.onlab.packet.Ethernet;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
@@ -35,17 +34,17 @@
import org.onosproject.net.packet.DefaultInboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
+import org.onosproject.net.pi.model.PiActionId;
+import org.onosproject.net.pi.model.PiActionParamId;
+import org.onosproject.net.pi.model.PiControlMetadataId;
+import org.onosproject.net.pi.model.PiCounterId;
+import org.onosproject.net.pi.model.PiMatchFieldId;
import org.onosproject.net.pi.model.PiPipelineInterpreter;
+import org.onosproject.net.pi.model.PiTableId;
import org.onosproject.net.pi.runtime.PiAction;
-import org.onosproject.net.pi.runtime.PiActionId;
import org.onosproject.net.pi.runtime.PiActionParam;
-import org.onosproject.net.pi.runtime.PiActionParamId;
-import org.onosproject.net.pi.runtime.PiCounterId;
-import org.onosproject.net.pi.runtime.PiHeaderFieldId;
-import org.onosproject.net.pi.runtime.PiPacketMetadata;
-import org.onosproject.net.pi.runtime.PiPacketMetadataId;
+import org.onosproject.net.pi.runtime.PiControlMetadata;
import org.onosproject.net.pi.runtime.PiPacketOperation;
-import org.onosproject.net.pi.runtime.PiTableId;
import java.nio.ByteBuffer;
import java.util.Collection;
@@ -59,7 +58,7 @@
import static org.onosproject.net.PortNumber.CONTROLLER;
import static org.onosproject.net.PortNumber.FLOOD;
import static org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT;
-import static org.onosproject.net.pi.runtime.PiPacketOperation.Type.PACKET_OUT;
+import static org.onosproject.net.pi.model.PiPacketOperationType.PACKET_OUT;
/**
* Implementation of a PI interpreter for the main.p4 program.
@@ -78,10 +77,10 @@
private static final String STANDARD_METADATA = "standard_metadata";
private static final int PORT_FIELD_BITWIDTH = 9;
- private static final PiHeaderFieldId INGRESS_PORT_ID = PiHeaderFieldId.of(STANDARD_METADATA, "ingress_port");
- private static final PiHeaderFieldId ETH_DST_ID = PiHeaderFieldId.of(ETHERNET, "dst_addr");
- private static final PiHeaderFieldId ETH_SRC_ID = PiHeaderFieldId.of(ETHERNET, "src_addr");
- private static final PiHeaderFieldId ETH_TYPE_ID = PiHeaderFieldId.of(ETHERNET, "ether_type");
+ private static final PiMatchFieldId INGRESS_PORT_ID = PiMatchFieldId.of(STANDARD_METADATA + ".ingress_port");
+ private static final PiMatchFieldId ETH_DST_ID = PiMatchFieldId.of(ETHERNET + ".dst_addr");
+ private static final PiMatchFieldId ETH_SRC_ID = PiMatchFieldId.of(ETHERNET + ".src_addr");
+ private static final PiMatchFieldId ETH_TYPE_ID = PiMatchFieldId.of(ETHERNET + ".ether_type");
private static final PiTableId TABLE0_ID = PiTableId.of(TABLE0);
private static final PiTableId IP_PROTO_FILTER_TABLE_ID = PiTableId.of(IP_PROTO_FILTER_TABLE);
@@ -89,8 +88,8 @@
0, TABLE0_ID,
1, IP_PROTO_FILTER_TABLE_ID);
- private static final BiMap<Criterion.Type, PiHeaderFieldId> CRITERION_MAP =
- new ImmutableBiMap.Builder<Criterion.Type, PiHeaderFieldId>()
+ private static final BiMap<Criterion.Type, PiMatchFieldId> CRITERION_MAP =
+ new ImmutableBiMap.Builder<Criterion.Type, PiMatchFieldId>()
.put(Criterion.Type.IN_PORT, INGRESS_PORT_ID)
.put(Criterion.Type.ETH_DST, ETH_DST_ID)
.put(Criterion.Type.ETH_SRC, ETH_SRC_ID)
@@ -177,7 +176,7 @@
}
@Override
- public InboundPacket mapInboundPacket(DeviceId deviceId, PiPacketOperation packetIn)
+ public InboundPacket mapInboundPacket(PiPacketOperation packetIn)
throws PiInterpreterException {
// We assume that the packet is ethernet, which is fine since default.p4 can deparse only ethernet packets.
Ethernet ethPkt;
@@ -188,34 +187,36 @@
}
// Returns the ingress port packet metadata.
- Optional<PiPacketMetadata> packetMetadata = packetIn.metadatas().stream()
- .filter(metadata -> metadata.id().name().equals(INGRESS_PORT))
+ Optional<PiControlMetadata> packetMetadata = packetIn.metadatas().stream()
+ .filter(metadata -> metadata.id().toString().equals(INGRESS_PORT))
.findFirst();
if (packetMetadata.isPresent()) {
ImmutableByteSequence portByteSequence = packetMetadata.get().value();
short s = portByteSequence.asReadOnlyBuffer().getShort();
- ConnectPoint receivedFrom = new ConnectPoint(deviceId, PortNumber.portNumber(s));
+ ConnectPoint receivedFrom = new ConnectPoint(packetIn.deviceId(), PortNumber.portNumber(s));
return new DefaultInboundPacket(receivedFrom, ethPkt, packetIn.data().asReadOnlyBuffer());
} else {
throw new PiInterpreterException(format(
- "Missing metadata '%s' in packet-in received from '%s': %s", INGRESS_PORT, deviceId, packetIn));
+ "Missing metadata '%s' in packet-in received from '%s': %s",
+ INGRESS_PORT, packetIn.deviceId(), packetIn));
}
}
private PiPacketOperation createPiPacketOperation(ByteBuffer data, long portNumber) throws PiInterpreterException {
- PiPacketMetadata metadata = createPacketMetadata(portNumber);
+ PiControlMetadata metadata = createControlMetadata(portNumber);
return PiPacketOperation.builder()
+ .forDevice(this.data().deviceId())
.withType(PACKET_OUT)
.withData(copyFrom(data))
.withMetadatas(ImmutableList.of(metadata))
.build();
}
- private PiPacketMetadata createPacketMetadata(long portNumber) throws PiInterpreterException {
+ private PiControlMetadata createControlMetadata(long portNumber) throws PiInterpreterException {
try {
- return PiPacketMetadata.builder()
- .withId(PiPacketMetadataId.of(EGRESS_PORT))
+ return PiControlMetadata.builder()
+ .withId(PiControlMetadataId.of(EGRESS_PORT))
.withValue(fit(copyFrom(portNumber), PORT_FIELD_BITWIDTH))
.build();
} catch (ImmutableByteSequence.ByteSequenceTrimException e) {
@@ -224,12 +225,12 @@
}
@Override
- public Optional<PiHeaderFieldId> mapCriterionType(Criterion.Type type) {
+ public Optional<PiMatchFieldId> mapCriterionType(Criterion.Type type) {
return Optional.ofNullable(CRITERION_MAP.get(type));
}
@Override
- public Optional<Criterion.Type> mapPiHeaderFieldId(PiHeaderFieldId headerFieldId) {
+ public Optional<Criterion.Type> mapPiMatchFieldId(PiMatchFieldId headerFieldId) {
return Optional.ofNullable(CRITERION_MAP.inverse().get(headerFieldId));
}
diff --git a/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PortStatisticsDiscoveryImpl.java b/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PortStatisticsDiscoveryImpl.java
index 7d715ee1..166958d 100644
--- a/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PortStatisticsDiscoveryImpl.java
+++ b/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PortStatisticsDiscoveryImpl.java
@@ -24,11 +24,10 @@
import org.onosproject.net.device.PortStatistics;
import org.onosproject.net.device.PortStatisticsDiscovery;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.pi.model.PiCounterId;
import org.onosproject.net.pi.model.PiPipeconf;
import org.onosproject.net.pi.runtime.PiCounterCellData;
import org.onosproject.net.pi.runtime.PiCounterCellId;
-import org.onosproject.net.pi.runtime.PiCounterId;
-import org.onosproject.net.pi.runtime.PiIndirectCounterCellId;
import org.onosproject.net.pi.runtime.PiPipeconfService;
import org.onosproject.p4runtime.api.P4RuntimeClient;
import org.onosproject.p4runtime.api.P4RuntimeController;
@@ -42,7 +41,7 @@
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
-import static org.onosproject.net.pi.runtime.PiCounterType.INDIRECT;
+import static org.onosproject.net.pi.model.PiCounterType.INDIRECT;
/**
* Implementation of the PortStatisticsDiscovery behaviour for the main.p4 program. This behaviour works by using a
@@ -52,8 +51,8 @@
private static final Logger log = LoggerFactory.getLogger(PortStatisticsDiscoveryImpl.class);
- private static final PiCounterId INGRESS_COUNTER_ID = PiCounterId.of("igr_port_counter", INDIRECT);
- private static final PiCounterId EGRESS_COUNTER_ID = PiCounterId.of("egr_port_counter", INDIRECT);
+ private static final PiCounterId INGRESS_COUNTER_ID = PiCounterId.of("igr_port_counter");
+ private static final PiCounterId EGRESS_COUNTER_ID = PiCounterId.of("egr_port_counter");
@Override
public Collection<PortStatistics> discoverPortStatistics() {
@@ -91,8 +90,8 @@
Set<PiCounterCellId> counterCellIds = Sets.newHashSet();
portStatBuilders.keySet().forEach(p -> {
// Counter cell/index = port number.
- counterCellIds.add(PiIndirectCounterCellId.of(INGRESS_COUNTER_ID, p));
- counterCellIds.add(PiIndirectCounterCellId.of(EGRESS_COUNTER_ID, p));
+ counterCellIds.add(PiCounterCellId.ofIndirect(INGRESS_COUNTER_ID, p));
+ counterCellIds.add(PiCounterCellId.ofIndirect(EGRESS_COUNTER_ID, p));
});
// Query the device.
@@ -107,16 +106,15 @@
// Process response.
counterEntryResponse.forEach(counterData -> {
- if (counterData.cellId().type() != INDIRECT) {
- log.warn("Invalid counter data type {}, skipping", counterData.cellId().type());
+ if (counterData.cellId().counterType() != INDIRECT) {
+ log.warn("Invalid counter data type {}, skipping", counterData.cellId().counterType());
return;
}
- PiIndirectCounterCellId indCellId = (PiIndirectCounterCellId) counterData.cellId();
- if (!portStatBuilders.containsKey(indCellId.index())) {
+ if (!portStatBuilders.containsKey(counterData.cellId().index())) {
log.warn("Unrecognized counter index {}, skipping", counterData);
return;
}
- DefaultPortStatistics.Builder statsBuilder = portStatBuilders.get(indCellId.index());
+ DefaultPortStatistics.Builder statsBuilder = portStatBuilders.get(counterData.cellId().index());
if (counterData.cellId().counterId().equals(INGRESS_COUNTER_ID)) {
statsBuilder.setPacketsReceived(counterData.packets());
statsBuilder.setBytesReceived(counterData.bytes());