[ONOS-6809] Implementation for packet out in p4Runtime
Change-Id: I873a1fd18529fe9fd41aa33f862298892ece7d1c
diff --git a/core/api/src/main/java/org/onosproject/net/pi/model/PiPipelineInterpreter.java b/core/api/src/main/java/org/onosproject/net/pi/model/PiPipelineInterpreter.java
index e71d910..25962ca 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/model/PiPipelineInterpreter.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/model/PiPipelineInterpreter.java
@@ -23,7 +23,7 @@
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.pi.runtime.PiHeaderFieldId;
-import org.onosproject.net.pi.runtime.PiPacketMetadata;
+import org.onosproject.net.pi.runtime.PiPacketOperation;
import org.onosproject.net.pi.runtime.PiTableAction;
import org.onosproject.net.pi.runtime.PiTableId;
@@ -79,15 +79,15 @@
throws PiInterpreterException;
/**
- * Returns a collection of metadatas for a packet-out operation that are equivalent to
- * the traffic treatment of the given OutboundPacket, for the given pipeline configuration.
+ * Returns a collection of packet operations equivalent to the given OutboundPacket, for the given
+ * pipeline configuration.
*
* @param packet a ONOS outbound packet
* @param pipeconf a pipeline configuration
- * @return a collection of packet metadata
+ * @return a collection of packet operations
* @throws PiInterpreterException if the packet treatments cannot be mapped to any metadata
*/
- Collection<PiPacketMetadata> mapOutboundPacket(OutboundPacket packet, PiPipeconf pipeconf)
+ Collection<PiPacketOperation> mapOutboundPacket(OutboundPacket packet, PiPipeconf pipeconf)
throws PiInterpreterException;
/**
diff --git a/core/net/src/test/java/org/onosproject/net/pi/impl/MockInterpreter.java b/core/net/src/test/java/org/onosproject/net/pi/impl/MockInterpreter.java
index ddee2ca..14e698d 100644
--- a/core/net/src/test/java/org/onosproject/net/pi/impl/MockInterpreter.java
+++ b/core/net/src/test/java/org/onosproject/net/pi/impl/MockInterpreter.java
@@ -17,6 +17,7 @@
package org.onosproject.net.pi.impl;
import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableList;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.net.PortNumber;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
@@ -31,7 +32,7 @@
import org.onosproject.net.pi.runtime.PiActionParam;
import org.onosproject.net.pi.runtime.PiActionParamId;
import org.onosproject.net.pi.runtime.PiHeaderFieldId;
-import org.onosproject.net.pi.runtime.PiPacketMetadata;
+import org.onosproject.net.pi.runtime.PiPacketOperation;
import org.onosproject.net.pi.runtime.PiTableAction;
import org.onosproject.net.pi.runtime.PiTableId;
@@ -102,9 +103,9 @@
}
@Override
- public Collection<PiPacketMetadata> mapOutboundPacket(OutboundPacket packet, PiPipeconf pipeconf)
+ public Collection<PiPacketOperation> mapOutboundPacket(OutboundPacket packet, PiPipeconf pipeconf)
throws PiInterpreterException {
- return null;
+ return ImmutableList.of();
}
/**
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2DefaultInterpreter.java b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2DefaultInterpreter.java
index 29e2a3a..a2e7812 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2DefaultInterpreter.java
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2DefaultInterpreter.java
@@ -17,8 +17,11 @@
package org.onosproject.drivers.bmv2;
import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableList;
import org.onlab.util.ImmutableByteSequence;
+import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
@@ -33,13 +36,21 @@
import org.onosproject.net.pi.runtime.PiActionParamId;
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.PiPacketOperation;
import org.onosproject.net.pi.runtime.PiTableAction;
import org.onosproject.net.pi.runtime.PiTableId;
+import java.nio.ByteBuffer;
import java.util.Collection;
+import java.util.List;
import java.util.Optional;
+import static java.util.stream.Collectors.toList;
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;
/**
* Interpreter implementation for the default pipeconf.
@@ -50,6 +61,8 @@
private static final String PORT = "port";
private static final String DROP = "_drop_0";
private static final String SET_EGRESS_PORT = "set_egress_port_0";
+ private static final String EGRESS_PORT = "egress_port";
+ private static final int PORT_NUMBER_BIT_WIDTH = 9;
private static final PiHeaderFieldId IN_PORT_ID = PiHeaderFieldId.of("standard_metadata", "ingress_port");
private static final PiHeaderFieldId ETH_DST_ID = PiHeaderFieldId.of("ethernet_t", "dstAddr");
@@ -67,6 +80,7 @@
private static final ImmutableBiMap<Integer, PiTableId> TABLE_MAP = ImmutableBiMap.of(
0, PiTableId.of(TABLE0));
+
@Override
public PiTableAction mapTreatment(TrafficTreatment treatment, PiPipeconf pipeconf) throws PiInterpreterException {
@@ -88,7 +102,7 @@
PiAction.builder()
.withId(PiActionId.of(SET_EGRESS_PORT))
.withParameter(new PiActionParam(PiActionParamId.of(PORT),
- ImmutableByteSequence.copyFrom(port.toLong())))
+ ImmutableByteSequence.copyFrom(port.toLong())))
.build();
} else if (port.equals(CONTROLLER)) {
return actionWithName(SEND_TO_CPU);
@@ -103,9 +117,65 @@
}
@Override
- public Collection<PiPacketMetadata> mapOutboundPacket(OutboundPacket packet, PiPipeconf pipeconf)
+ public Collection<PiPacketOperation> mapOutboundPacket(OutboundPacket packet, PiPipeconf pipeconf)
throws PiInterpreterException {
- throw new UnsupportedOperationException("Currently unsupported");
+ TrafficTreatment treatment = packet.treatment();
+
+ // default.p4 supports only OUTPUT instructions.
+ List<Instructions.OutputInstruction> outInstructions = treatment.allInstructions()
+ .stream()
+ .filter(i -> i.type().equals(OUTPUT))
+ .map(i -> (Instructions.OutputInstruction) i)
+ .collect(toList());
+
+ if (treatment.allInstructions().size() != outInstructions.size()) {
+ // There are other instructions that are not of type OUTPUT
+ throw new PiInterpreterException("Treatment not supported: " + treatment);
+ }
+
+ ImmutableList.Builder<PiPacketOperation> builder = ImmutableList.builder();
+ for (Instructions.OutputInstruction outInst : outInstructions) {
+ if (outInst.port().isLogical() && !outInst.port().equals(FLOOD)) {
+ throw new PiInterpreterException("Logical port not supported: " +
+ outInst.port());
+ } else if (outInst.port().equals(FLOOD)) {
+ //Since default.p4 does not support flood for each port of the device
+ // create a packet operation to send the packet out of that specific port
+ for (Port port : handler().get(DeviceService.class).getPorts(packet.sendThrough())) {
+ builder.add(createPiPacketOperation(packet.data(), port.number().toLong()));
+ }
+ } else {
+ builder.add(createPiPacketOperation(packet.data(), outInst.port().toLong()));
+ }
+ }
+ return builder.build();
+ }
+
+ private PiPacketOperation createPiPacketOperation(ByteBuffer data, long portNumber) throws PiInterpreterException {
+ //create the metadata
+ PiPacketMetadata metadata = createPacketMetadata(portNumber);
+
+ //Create the Packet operation
+ return PiPacketOperation.builder()
+ .withType(PACKET_OUT)
+ .withData(ImmutableByteSequence.copyFrom(data))
+ .withMetadatas(ImmutableList.of(metadata))
+ .build();
+ }
+
+ private PiPacketMetadata createPacketMetadata(long portNumber) throws PiInterpreterException {
+ ImmutableByteSequence portValue = ImmutableByteSequence.copyFrom(portNumber);
+ //FIXME remove hardcoded bitWidth and retrieve it from pipelineModel
+ try {
+ portValue = ImmutableByteSequence.fit(portValue, PORT_NUMBER_BIT_WIDTH);
+ } catch (ImmutableByteSequence.ByteSequenceTrimException e) {
+ throw new PiInterpreterException("Port number too big: {}" +
+ portNumber + " causes " + e.getMessage());
+ }
+ return PiPacketMetadata.builder()
+ .withId(PiPacketMetadataId.of(EGRESS_PORT))
+ .withValue(portValue)
+ .build();
}
/**
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PacketProgrammable.java b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PacketProgrammable.java
index c4dc2b4..cbf032b 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PacketProgrammable.java
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PacketProgrammable.java
@@ -16,7 +16,6 @@
package org.onosproject.drivers.bmv2;
-import org.onlab.util.ImmutableByteSequence;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
@@ -32,7 +31,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import static org.onosproject.net.pi.runtime.PiPacketOperation.Type.PACKET_OUT;
+import java.util.Collection;
/**
* Packet Programmable behaviour for BMv2 devices.
@@ -72,16 +71,13 @@
}
try {
- PiPacketOperation piPacketOperation = PiPacketOperation
- .builder()
- .withType(PACKET_OUT)
- .withData(ImmutableByteSequence.copyFrom(packet.data()))
- .withMetadatas(interpreter.mapOutboundPacket(packet, pipeconf))
- .build();
- client.packetOut(piPacketOperation, pipeconf);
+ Collection<PiPacketOperation> operations = interpreter.mapOutboundPacket(packet, pipeconf);
+ operations.forEach(piPacketOperation -> {
+ client.packetOut(piPacketOperation, pipeconf);
+ });
} catch (PiPipelineInterpreter.PiInterpreterException e) {
log.error("Interpreter of pipeconf {} was unable to translate outbound packet: {}",
- pipeconf.id(), e.getMessage());
+ pipeconf.id(), e.getMessage());
}
}
}
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4InfoBrowser.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4InfoBrowser.java
index b24bc70..ee1e608 100644
--- a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4InfoBrowser.java
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4InfoBrowser.java
@@ -53,6 +53,8 @@
new EntityBrowser<>("controller packet metadata");
private final Map<Integer, EntityBrowser<Action.Param>> actionParams = Maps.newHashMap();
private final Map<Integer, EntityBrowser<MatchField>> matchFields = Maps.newHashMap();
+ private final Map<Integer, EntityBrowser<ControllerPacketMetadata.Metadata>> ctrlPktMetadatasMetadata =
+ Maps.newHashMap();
/**
* Creates a new browser for the given P4Info.
@@ -107,7 +109,16 @@
entity -> directMeters.addWithPreamble(entity.getPreamble(), entity));
p4info.getControllerPacketMetadataList().forEach(
- entity -> ctrlPktMetadatas.addWithPreamble(entity.getPreamble(), entity));
+ entity -> {
+ ctrlPktMetadatas.addWithPreamble(entity.getPreamble(), entity);
+ // Index control packet metadata metadata.
+ int ctrlPktMetadataId = entity.getPreamble().getId();
+ String ctrlPktMetadataName = entity.getPreamble().getName();
+ EntityBrowser<ControllerPacketMetadata.Metadata> metadataBrowser = new EntityBrowser<>(format(
+ "metadata field for controller packet metadata '%s'", ctrlPktMetadataName));
+ entity.getMetadataList().forEach(m -> metadataBrowser.add(m.getName(), null, m.getId(), m));
+ ctrlPktMetadatasMetadata.put(ctrlPktMetadataId, metadataBrowser);
+ });
}
private String extractMatchFieldSimpleName(String name) {
@@ -212,7 +223,7 @@
* Returns a browser for match fields of the given table.
*
* @param tableId table identifier
- * @return controller packet metadata browser
+ * @return match field browser
* @throws NotFoundException if the table cannot be found
*/
EntityBrowser<MatchField> matchFields(int tableId) throws NotFoundException {
@@ -222,6 +233,20 @@
}
/**
+ * Returns a browser for metadata fields of the controller packet metadata.
+ *
+ * @param controllerPacketMetadataId controller packet metadata identifier
+ * @return metadata browser
+ * @throws NotFoundException controller packet metadata cannot be foudn
+ */
+ EntityBrowser<ControllerPacketMetadata.Metadata> packetMetadatas(int controllerPacketMetadataId)
+ throws NotFoundException {
+ // Throws exception if controller packet metadata id is not found.
+ ctrlPktMetadatas.getById(controllerPacketMetadataId);
+ return ctrlPktMetadatasMetadata.get(controllerPacketMetadataId);
+ }
+
+ /**
* Browser of P4Info entities.
*
* @param <T> protobuf message type
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java
index 132689a..bb2d16b 100644
--- a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java
@@ -47,6 +47,7 @@
import p4.P4RuntimeOuterClass.Uint128;
import p4.P4RuntimeOuterClass.Update;
import p4.P4RuntimeOuterClass.WriteRequest;
+import p4.config.P4InfoOuterClass.P4Info;
import p4.tmp.P4Config;
import java.io.IOException;
@@ -72,8 +73,8 @@
import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType;
import static org.slf4j.LoggerFactory.getLogger;
import static p4.P4RuntimeOuterClass.Entity.EntityCase.TABLE_ENTRY;
+import static p4.P4RuntimeOuterClass.PacketOut;
import static p4.P4RuntimeOuterClass.SetForwardingPipelineConfigRequest.Action.VERIFY_AND_COMMIT;
-import static p4.config.P4InfoOuterClass.P4Info;
/**
* Implementation of a P4Runtime client.
@@ -162,33 +163,7 @@
@Override
public CompletableFuture<Boolean> packetOut(PiPacketOperation packet, PiPipeconf pipeconf) {
- CompletableFuture<Boolean> result = new CompletableFuture<>();
-// P4InfoBrowser browser = null; //PipeconfHelper.getP4InfoBrowser(pipeconf);
-// try {
-// ControllerPacketMetadata controllerPacketMetadata =
-// browser.controllerPacketMetadatas().getByName("packet_out");
-// PacketOut.Builder packetOutBuilder = PacketOut.newBuilder();
-// packetOutBuilder.addAllMetadata(packet.metadatas().stream().map(metadata -> {
-// //FIXME we are assuming that there is no more than one metadata per name.
-// int metadataId = controllerPacketMetadata.getMetadataList().stream().filter(metadataInfo -> {
-// return metadataInfo.getName().equals(metadata.id().name());
-// }).findFirst().get().getId();
-// return PacketMetadata.newBuilder()
-// .setMetadataId(metadataId)
-// .setValue(ByteString.copyFrom(metadata.value().asReadOnlyBuffer()))
-// .build();
-// }).filter(Objects::nonNull).collect(Collectors.toList()));
-// packetOutBuilder.setPayload(ByteString.copyFrom(packet.data().asReadOnlyBuffer()));
-// PacketOut packetOut = packetOutBuilder.build();
-// StreamMessageRequest packetOutRequest = StreamMessageRequest
-// .newBuilder().setPacket(packetOut).build();
-// streamRequestObserver.onNext(packetOutRequest);
-// result.complete(true);
-// } catch (P4InfoBrowser.NotFoundException e) {
-// log.error("Cant find metadata with name \"packet_out\" in p4Info file.");
-// result.complete(false);
-// }
- return result;
+ return supplyInContext(() -> doPacketOut(packet, pipeconf));
}
/* Blocking method implementations below */
@@ -354,6 +329,27 @@
return TableEntryEncoder.decode(tableEntryMsgs, pipeconf);
}
+ private boolean doPacketOut(PiPacketOperation packet, PiPipeconf pipeconf) {
+ try {
+ //encode the PiPacketOperation into a PacketOut
+ PacketOut packetOut = PacketIOCodec.encodePacketOut(packet, pipeconf);
+
+ //Build the request
+ StreamMessageRequest packetOutRequest = StreamMessageRequest
+ .newBuilder().setPacket(packetOut).build();
+
+ //Send the request
+ streamRequestObserver.onNext(packetOutRequest);
+
+ } catch (P4InfoBrowser.NotFoundException e) {
+ log.error("Cant find expected metadata in p4Info file. {}", e.getMessage());
+ log.debug("Exception", e);
+ return false;
+ }
+ return true;
+ }
+
+
@Override
public void shutdown() {
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/PacketIOCodec.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/PacketIOCodec.java
new file mode 100644
index 0000000..0461154
--- /dev/null
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/PacketIOCodec.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.p4runtime.ctl;
+
+import com.google.protobuf.ByteString;
+import org.onosproject.net.pi.model.PiPipeconf;
+import org.onosproject.net.pi.runtime.PiPacketOperation;
+import org.slf4j.Logger;
+import p4.P4RuntimeOuterClass;
+import p4.config.P4InfoOuterClass;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import static org.onosproject.p4runtime.ctl.P4InfoBrowser.*;
+import static org.slf4j.LoggerFactory.getLogger;
+import static p4.P4RuntimeOuterClass.PacketMetadata;
+
+/**
+ * Encoder of packet metadata, from ONOS Pi* format, to P4Runtime protobuf messages, and vice versa.
+ */
+final class PacketIOCodec {
+
+ private static final Logger log = getLogger(PacketIOCodec.class);
+
+ private static final String PACKET_OUT = "packet_out";
+
+ // TODO: implement cache of encoded entities.
+
+ private PacketIOCodec() {
+ // hide.
+ }
+
+ /**
+ * Returns a P4Runtime packet out protobuf message, encoded from the given PiPacketOperation
+ * for the given pipeconf. If a PI packet metadata inside the PacketOperation cannot be encoded,
+ * it is skipped, hence the returned PacketOut collection of metadatas might have different
+ * size than the input one.
+ * <p>
+ * Please check the log for an explanation of any error that might have occurred.
+ *
+ * @param packet PI pakcet operation
+ * @param pipeconf the pipeconf for the program on the switch
+ * @return a P4Runtime packet out protobuf message
+ * @throws NotFoundException if the browser can't find the packet_out in the given p4Info
+ */
+ static P4RuntimeOuterClass.PacketOut encodePacketOut(PiPacketOperation packet, PiPipeconf pipeconf)
+ throws NotFoundException {
+
+ //Get the P4browser
+ P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
+
+ //Get the packet out packet metadata
+ P4InfoOuterClass.ControllerPacketMetadata controllerPacketMetadata =
+ browser.controllerPacketMetadatas().getByName(PACKET_OUT);
+ P4RuntimeOuterClass.PacketOut.Builder packetOutBuilder = P4RuntimeOuterClass.PacketOut.newBuilder();
+
+ //outer controller packet metadata id
+ int controllerPacketMetadataId = controllerPacketMetadata.getPreamble().getId();
+
+ //Add all its metadata to the packet out
+ packetOutBuilder.addAllMetadata(encodePacketMetadata(packet, browser, controllerPacketMetadataId));
+
+ //Set the packet out payload
+ packetOutBuilder.setPayload(ByteString.copyFrom(packet.data().asReadOnlyBuffer()));
+ return packetOutBuilder.build();
+
+ }
+
+ private static List<PacketMetadata> encodePacketMetadata(PiPacketOperation packet,
+ P4InfoBrowser browser, int controllerPacketMetadataId) {
+ return packet.metadatas().stream().map(metadata -> {
+ try {
+ //get each metadata id
+ int metadataId = browser.packetMetadatas(controllerPacketMetadataId)
+ .getByName(metadata.id().name()).getId();
+
+ //Add the metadata id and it's data the packet out
+ return PacketMetadata.newBuilder()
+ .setMetadataId(metadataId)
+ .setValue(ByteString.copyFrom(metadata.value().asReadOnlyBuffer()))
+ .build();
+ } catch (NotFoundException e) {
+ log.error("Cant find metadata with name {} in p4Info file.", metadata.id().name());
+ return null;
+ }
+ }).filter(Objects::nonNull).collect(Collectors.toList());
+ }
+
+ //TODO: add decode packets
+
+}
diff --git a/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java b/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java
index daeb62f..92ad3ca 100644
--- a/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java
+++ b/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java
@@ -32,6 +32,7 @@
import org.onosproject.net.pi.runtime.PiTableEntry;
import org.onosproject.net.pi.runtime.PiTableId;
import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
+import org.slf4j.Logger;
import p4.P4RuntimeOuterClass.Action;
import p4.P4RuntimeOuterClass.TableEntry;
@@ -48,9 +49,15 @@
import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.P4_INFO_TEXT;
import static org.onosproject.p4runtime.ctl.TableEntryEncoder.decode;
import static org.onosproject.p4runtime.ctl.TableEntryEncoder.encode;
+import static org.slf4j.LoggerFactory.getLogger;
+
+//import org.onosproject.driver.pipeline.DefaultSingleTablePipeline;
+//import org.onosproject.drivers.bmv2.Bmv2DefaultInterpreter;
public class TableEntryEncoderTest {
+ private final Logger log = getLogger(getClass());
+
private static final String TABLE_0 = "table0";
private static final String SET_EGRESS_PORT = "set_egress_port";
private static final String PORT = "port";
@@ -68,6 +75,7 @@
private final PiPipeconf defaultPipeconf = DefaultPiPipeconf.builder()
.withId(new PiPipeconfId("mock"))
.withPipelineModel(Bmv2PipelineModelParser.parse(jsonUrl))
+// .addBehaviour(PiPipelineInterpreter.class, Bmv2DefaultInterpreter.class)
.addExtension(P4_INFO_TEXT, p4InfoUrl)
.addExtension(BMV2_JSON, jsonUrl)
.build();
@@ -91,10 +99,10 @@
.withFieldMatch(new PiTernaryFieldMatch(inPortFieldId, portValue, ImmutableByteSequence.ofOnes(2)))
.withFieldMatch(new PiTernaryFieldMatch(ethTypeFieldId, portValue, ImmutableByteSequence.ofOnes(2)))
.withAction(PiAction
- .builder()
- .withId(outActionId)
- .withParameter(new PiActionParam(portParamId, portValue))
- .build())
+ .builder()
+ .withId(outActionId)
+ .withParameter(new PiActionParam(portParamId, portValue))
+ .build())
.withPriority(1)
.withCookie(2)
.build();
@@ -165,19 +173,20 @@
}
// @Test
-// public void testRuntime() throws ExecutionException, InterruptedException {
+// public void testRuntime() throws ExecutionException, InterruptedException,
+// PiPipelineInterpreter.PiInterpreterException, IllegalAccessException, InstantiationException {
//
// // FIXME: remove me.
//
// P4RuntimeControllerImpl controller = new P4RuntimeControllerImpl();
// GrpcControllerImpl grpcController = new GrpcControllerImpl();
// controller.grpcController = grpcController;
-// GrpcControllerImpl.ENABLE_MESSAGE_LOG = true;
+// GrpcControllerImpl.enableMessageLog = true;
// grpcController.activate();
// DeviceId deviceId = DeviceId.deviceId("dummy:1");
//
// ManagedChannelBuilder channelBuilder = NettyChannelBuilder
-// .forAddress("192.168.56.102", 55044)
+// .forAddress("192.168.56.102", 59975)
// .usePlaintext(true);
//
// assert (controller.createClient(deviceId, 1, channelBuilder));
@@ -188,10 +197,37 @@
//
// assert(client.initStreamChannel().get());
//
-// assert(client.dumpTable(PiTableId.of(TABLE_0), defaultPipeconf).get().size() == 0);
+// log.info("++++++++++++++++++++++++++++");
//
-// assert(client.writeTableEntries(Lists.newArrayList(piTableEntry), INSERT, defaultPipeconf).get());
+// PiPipelineInterpreter interpreter = (PiPipelineInterpreter) defaultPipeconf
+// .implementation(PiPipelineInterpreter.class)
+// .orElse(null)
+// .newInstance();
//
-// assert(client.dumpTable(PiTableId.of(TABLE_0), defaultPipeconf).get().size() == 1);
+// TrafficTreatment t = DefaultTrafficTreatment.builder()
+// .setOutput(PortNumber.portNumber(830L)).build();
+// byte[] payload = new byte[1000];
+//// payload[0] = 1;
+// Arrays.fill( payload, (byte) 1 );
+//
+// OutboundPacket packet = new DefaultOutboundPacket(
+// deviceId, t, ByteBuffer.wrap(payload));
+//
+//
+// Collection<PiPacketOperation> operations = interpreter.mapOutboundPacket(packet,defaultPipeconf);
+// log.info("{}", operations);
+// operations.forEach(piPacketOperation -> {
+// try {
+// client.packetOut(piPacketOperation, defaultPipeconf).get();
+// } catch (InterruptedException | ExecutionException e) {
+// log.error("{}",e);
+// }
+// });
+//
+//// assert(client.dumpTable(PiTableId.of(TABLE_0), defaultPipeconf).get().size() == 0);
+//
+//// assert(client.writeTableEntries(Lists.newArrayList(piTableEntry), INSERT, defaultPipeconf).get());
+//
+//// assert(client.dumpTable(PiTableId.of(TABLE_0), defaultPipeconf).get().size() == 1);
// }
}
diff --git a/protocols/p4runtime/ctl/src/test/resources/default.p4info b/protocols/p4runtime/ctl/src/test/resources/default.p4info
index bd3649d..b224b87 100644
--- a/protocols/p4runtime/ctl/src/test/resources/default.p4info
+++ b/protocols/p4runtime/ctl/src/test/resources/default.p4info
@@ -111,3 +111,37 @@
}
direct_table_id: 33617813
}
+controller_packet_metadata {
+ preamble {
+ id: 2868941301
+ name: "packet_in"
+ annotations: "@controller_header(\"packet_in\")"
+ }
+ metadata {
+ id: 1
+ name: "ingress_port"
+ bitwidth: 9
+ }
+ metadata {
+ id: 2
+ name: "other1"
+ bitwidth: 32
+ }
+}
+controller_packet_metadata {
+ preamble {
+ id: 2868916615
+ name: "packet_out"
+ annotations: "@controller_header(\"packet_out\")"
+ }
+ metadata {
+ id: 1
+ name: "egress_port"
+ bitwidth: 9
+ }
+ metadata {
+ id: 2
+ name: "other2"
+ bitwidth: 32
+ }
+}
diff --git a/tools/test/p4src/p4-16/default.p4 b/tools/test/p4src/p4-16/default.p4
index 71a48b5..36e6279 100644
--- a/tools/test/p4src/p4-16/default.p4
+++ b/tools/test/p4src/p4-16/default.p4
@@ -39,4 +39,16 @@
}
}
+@controller_header("packet_in")
+header packet_in_header_t {
+ bit<9> ingress_port;
+ bit<32> other1;
+}
+
+@controller_header("packet_out")
+header packet_out_header_t {
+ bit<9> egress_port;
+ bit<32> other2;
+}
+
V1Switch(ParserImpl(), verifyChecksum(), ingress(), egress(), computeChecksum(), DeparserImpl()) main;