mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-18 19:01:06 +02:00
Pi classes to support P4Runtime action profiles
+ modified default.p4 with ECMP capabilities (via action profiles) + sketched translation logic of ONOS groups (in Bmv2GroupProgrammable) + replaced existing instances of default.json/p4info with symlinks to p4src build directory (to avoid inconsistencies) Change-Id: If82f0b8ce296c9b616415d99864d216b77645a87
This commit is contained in:
parent
f3a1a3897e
commit
b2e3dbaef0
@ -8,6 +8,7 @@ COMPILE_DEPS = [
|
|||||||
'//protocols/p4runtime/api:onos-protocols-p4runtime-api',
|
'//protocols/p4runtime/api:onos-protocols-p4runtime-api',
|
||||||
'//protocols/p4runtime/ctl:onos-protocols-p4runtime-ctl',
|
'//protocols/p4runtime/ctl:onos-protocols-p4runtime-ctl',
|
||||||
'//protocols/p4runtime/proto:onos-protocols-p4runtime-proto',
|
'//protocols/p4runtime/proto:onos-protocols-p4runtime-proto',
|
||||||
|
'//drivers/bmv2:onos-drivers-bmv2',
|
||||||
'//incubator/grpc-dependencies:grpc-core-repkg-' + GRPC_VER,
|
'//incubator/grpc-dependencies:grpc-core-repkg-' + GRPC_VER,
|
||||||
'//lib:grpc-stub-' + GRPC_VER,
|
'//lib:grpc-stub-' + GRPC_VER,
|
||||||
'//lib:protobuf-java-' + PROTOBUF_VER,
|
'//lib:protobuf-java-' + PROTOBUF_VER,
|
||||||
|
@ -18,66 +18,165 @@ package org.onosproject.p4runtime.test;
|
|||||||
|
|
||||||
import io.grpc.ManagedChannelBuilder;
|
import io.grpc.ManagedChannelBuilder;
|
||||||
import io.grpc.netty.NettyChannelBuilder;
|
import io.grpc.netty.NettyChannelBuilder;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.onlab.util.ImmutableByteSequence;
|
||||||
import org.onosproject.bmv2.model.Bmv2PipelineModelParser;
|
import org.onosproject.bmv2.model.Bmv2PipelineModelParser;
|
||||||
|
import org.onosproject.drivers.bmv2.Bmv2DefaultInterpreter;
|
||||||
import org.onosproject.grpc.ctl.GrpcControllerImpl;
|
import org.onosproject.grpc.ctl.GrpcControllerImpl;
|
||||||
import org.onosproject.net.DeviceId;
|
import org.onosproject.net.DeviceId;
|
||||||
import org.onosproject.net.pi.model.DefaultPiPipeconf;
|
import org.onosproject.net.pi.model.DefaultPiPipeconf;
|
||||||
import org.onosproject.net.pi.model.PiPipeconf;
|
import org.onosproject.net.pi.model.PiPipeconf;
|
||||||
import org.onosproject.net.pi.model.PiPipeconfId;
|
import org.onosproject.net.pi.model.PiPipeconfId;
|
||||||
import org.onosproject.net.pi.model.PiPipelineInterpreter;
|
import org.onosproject.net.pi.model.PiPipelineInterpreter;
|
||||||
import org.onosproject.p4runtime.api.P4RuntimeClient;
|
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.PiTableId;
|
||||||
|
import org.onosproject.p4runtime.ctl.P4RuntimeClientImpl;
|
||||||
import org.onosproject.p4runtime.ctl.P4RuntimeControllerImpl;
|
import org.onosproject.p4runtime.ctl.P4RuntimeControllerImpl;
|
||||||
|
import p4.P4RuntimeGrpc;
|
||||||
|
import p4.P4RuntimeOuterClass;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
import static org.onlab.util.ImmutableByteSequence.copyFrom;
|
||||||
|
import static org.onlab.util.ImmutableByteSequence.fit;
|
||||||
import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.BMV2_JSON;
|
import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.BMV2_JSON;
|
||||||
import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.P4_INFO_TEXT;
|
import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.P4_INFO_TEXT;
|
||||||
|
import static org.onosproject.net.pi.runtime.PiPacketOperation.Type.PACKET_OUT;
|
||||||
|
import static p4.P4RuntimeOuterClass.ActionProfileGroup.Type.SELECT;
|
||||||
|
import static p4.P4RuntimeOuterClass.Update.Type.INSERT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used for quick testing of P4Runtime with real devices. To be removed before release.
|
* Class used for quick testing of P4Runtime with real devices. To be removed before release.
|
||||||
*/
|
*/
|
||||||
public class P4RuntimeTest {
|
public class P4RuntimeTest {
|
||||||
|
|
||||||
private final URL p4InfoUrl = this.getClass().getResource("/default.p4info");
|
private static final String GRPC_SERVER_ADDR = "192.168.56.102";
|
||||||
private final URL jsonUrl = this.getClass().getResource("/default.json");
|
private static final int GRPC_SERVER_PORT = 55044;
|
||||||
|
|
||||||
|
private final URL p4InfoUrl = this.getClass().getResource("/bmv2/default.p4info");
|
||||||
|
private final URL jsonUrl = this.getClass().getResource("/bmv2/default.json");
|
||||||
|
|
||||||
private final PiPipeconf bmv2DefaultPipeconf = DefaultPiPipeconf.builder()
|
private final PiPipeconf bmv2DefaultPipeconf = DefaultPiPipeconf.builder()
|
||||||
.withId(new PiPipeconfId("mock"))
|
.withId(new PiPipeconfId("mock-bmv2"))
|
||||||
.withPipelineModel(Bmv2PipelineModelParser.parse(jsonUrl))
|
.withPipelineModel(Bmv2PipelineModelParser.parse(jsonUrl))
|
||||||
// .addBehaviour(PiPipelineInterpreter.class, Bmv2DefaultInterpreter.class)
|
.addBehaviour(PiPipelineInterpreter.class, Bmv2DefaultInterpreter.class)
|
||||||
.addExtension(P4_INFO_TEXT, p4InfoUrl)
|
.addExtension(P4_INFO_TEXT, p4InfoUrl)
|
||||||
.addExtension(BMV2_JSON, jsonUrl)
|
.addExtension(BMV2_JSON, jsonUrl)
|
||||||
.build();
|
.build();
|
||||||
|
private final P4RuntimeControllerImpl controller = new P4RuntimeControllerImpl();
|
||||||
|
private final GrpcControllerImpl grpcController = new GrpcControllerImpl();
|
||||||
|
private final DeviceId deviceId = DeviceId.deviceId("dummy:1");
|
||||||
|
private final ManagedChannelBuilder channelBuilder = NettyChannelBuilder
|
||||||
|
.forAddress(GRPC_SERVER_ADDR, GRPC_SERVER_PORT)
|
||||||
|
.usePlaintext(true);
|
||||||
|
private P4RuntimeClientImpl client;
|
||||||
|
|
||||||
@Test
|
@Before
|
||||||
@Ignore
|
public void setUp() throws Exception {
|
||||||
public void testRuntime() throws ExecutionException, InterruptedException,
|
|
||||||
PiPipelineInterpreter.PiInterpreterException, IllegalAccessException, InstantiationException {
|
|
||||||
|
|
||||||
// FIXME: remove me.
|
|
||||||
|
|
||||||
P4RuntimeControllerImpl controller = new P4RuntimeControllerImpl();
|
|
||||||
GrpcControllerImpl grpcController = new GrpcControllerImpl();
|
|
||||||
controller.grpcController = grpcController;
|
controller.grpcController = grpcController;
|
||||||
GrpcControllerImpl.enableMessageLog = true;
|
GrpcControllerImpl.enableMessageLog = true;
|
||||||
grpcController.activate();
|
grpcController.activate();
|
||||||
DeviceId deviceId = DeviceId.deviceId("dummy:1");
|
}
|
||||||
|
|
||||||
ManagedChannelBuilder channelBuilder = NettyChannelBuilder
|
private void createClientAndSetPipelineConfig(PiPipeconf pipeconf, PiPipeconf.ExtensionType extensionType)
|
||||||
.forAddress("192.168.56.102", 59975)
|
throws ExecutionException, InterruptedException, PiPipelineInterpreter.PiInterpreterException,
|
||||||
.usePlaintext(true);
|
IllegalAccessException, InstantiationException {
|
||||||
|
|
||||||
assert (controller.createClient(deviceId, 1, channelBuilder));
|
assert (controller.createClient(deviceId, 1, channelBuilder));
|
||||||
|
|
||||||
P4RuntimeClient client = controller.getClient(deviceId);
|
client = (P4RuntimeClientImpl) controller.getClient(deviceId);
|
||||||
|
|
||||||
assert (client.setPipelineConfig(bmv2DefaultPipeconf, PiPipeconf.ExtensionType.BMV2_JSON).get());
|
|
||||||
|
|
||||||
|
assert (client.setPipelineConfig(pipeconf, extensionType).get());
|
||||||
assert (client.initStreamChannel().get());
|
assert (client.initStreamChannel().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testActionProfile(int actionProfileId) {
|
||||||
|
|
||||||
|
P4RuntimeGrpc.P4RuntimeBlockingStub stub = client.blockingStub();
|
||||||
|
|
||||||
|
P4RuntimeOuterClass.ActionProfileMember profileMemberMsg = P4RuntimeOuterClass.ActionProfileMember.newBuilder()
|
||||||
|
.setActionProfileId(actionProfileId)
|
||||||
|
// .setMemberId(1)
|
||||||
|
.setAction(P4RuntimeOuterClass.Action.newBuilder()
|
||||||
|
.setActionId(16793508)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
P4RuntimeOuterClass.ActionProfileGroup groupMsg = P4RuntimeOuterClass.ActionProfileGroup.newBuilder()
|
||||||
|
.setActionProfileId(actionProfileId)
|
||||||
|
.setGroupId(1)
|
||||||
|
.setType(SELECT)
|
||||||
|
.addMembers(P4RuntimeOuterClass.ActionProfileGroup.Member.newBuilder()
|
||||||
|
.setMemberId(1)
|
||||||
|
.setWeight(1)
|
||||||
|
.build())
|
||||||
|
.setMaxSize(3)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
P4RuntimeOuterClass.WriteRequest writeRequest = P4RuntimeOuterClass.WriteRequest.newBuilder()
|
||||||
|
.setDeviceId(client.p4DeviceId())
|
||||||
|
.addUpdates(P4RuntimeOuterClass.Update.newBuilder()
|
||||||
|
.setType(INSERT)
|
||||||
|
.setEntity(P4RuntimeOuterClass.Entity.newBuilder()
|
||||||
|
.setActionProfileGroup(groupMsg)
|
||||||
|
.build())
|
||||||
|
.build())
|
||||||
|
.addUpdates(P4RuntimeOuterClass.Update.newBuilder()
|
||||||
|
.setType(INSERT)
|
||||||
|
.setEntity(P4RuntimeOuterClass.Entity.newBuilder()
|
||||||
|
.setActionProfileMember(profileMemberMsg)
|
||||||
|
.build())
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
stub.write(writeRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testPacketOut() throws IllegalAccessException, InstantiationException, ExecutionException,
|
||||||
|
InterruptedException, ImmutableByteSequence.ByteSequenceTrimException {
|
||||||
|
|
||||||
|
PiPacketOperation packetOperation = PiPacketOperation.builder()
|
||||||
|
.withData(ImmutableByteSequence.ofOnes(10))
|
||||||
|
.withType(PACKET_OUT)
|
||||||
|
.withMetadata(PiPacketMetadata.builder()
|
||||||
|
.withId(PiPacketMetadataId.of("egress_port"))
|
||||||
|
.withValue(fit(copyFrom(1), 9))
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert (client.packetOut(packetOperation, bmv2DefaultPipeconf).get());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testDumpTable(String tableName, PiPipeconf pipeconf) throws ExecutionException, InterruptedException {
|
||||||
|
assert (client.dumpTable(PiTableId.of(tableName), pipeconf).get().size() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void testBmv2() throws Exception {
|
||||||
|
|
||||||
|
createClientAndSetPipelineConfig(bmv2DefaultPipeconf, BMV2_JSON);
|
||||||
|
|
||||||
|
testDumpTable("table0", bmv2DefaultPipeconf);
|
||||||
|
|
||||||
|
// testPacketOut();
|
||||||
|
|
||||||
|
testActionProfile(285261835);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore
|
||||||
|
public void testTofino() throws Exception {
|
||||||
|
|
||||||
|
createClientAndSetPipelineConfig(bmv2DefaultPipeconf, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// OLD STUFF
|
||||||
// log.info("++++++++++++++++++++++++++++");
|
// log.info("++++++++++++++++++++++++++++");
|
||||||
//
|
//
|
||||||
// PiPipelineInterpreter interpreter = (PiPipelineInterpreter) defaultPipeconf
|
// PiPipelineInterpreter interpreter = (PiPipelineInterpreter) defaultPipeconf
|
||||||
@ -111,4 +210,3 @@ public class P4RuntimeTest {
|
|||||||
|
|
||||||
// assert(client.dumpTable(PiTableId.of(TABLE_0), defaultPipeconf).get().size() == 1);
|
// assert(client.dumpTable(PiTableId.of(TABLE_0), defaultPipeconf).get().size() == 1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
1
apps/p4runtime-test/src/test/resources/bmv2/default.json
Symbolic link
1
apps/p4runtime-test/src/test/resources/bmv2/default.json
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../../tools/test/p4src/p4-16/p4c-out/default.json
|
1
apps/p4runtime-test/src/test/resources/bmv2/default.p4info
Symbolic link
1
apps/p4runtime-test/src/test/resources/bmv2/default.p4info
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../../tools/test/p4src/p4-16/p4c-out/default.p4info
|
@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* 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.net.pi.runtime;
|
||||||
|
|
||||||
|
import com.google.common.annotations.Beta;
|
||||||
|
import com.google.common.base.MoreObjects;
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action group of a protocol-independent pipeline.
|
||||||
|
*/
|
||||||
|
@Beta
|
||||||
|
public final class PiActionGroup {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of action group.
|
||||||
|
*/
|
||||||
|
public enum Type {
|
||||||
|
/**
|
||||||
|
* Load-balancing among different members in a group.
|
||||||
|
*/
|
||||||
|
SELECT
|
||||||
|
}
|
||||||
|
|
||||||
|
private final PiActionGroupId id;
|
||||||
|
private final Type type;
|
||||||
|
private final ImmutableSet<PiActionGroupMember> members;
|
||||||
|
|
||||||
|
private PiActionGroup(PiActionGroupId id, Type type, ImmutableSet<PiActionGroupMember> members) {
|
||||||
|
this.id = id;
|
||||||
|
this.type = type;
|
||||||
|
this.members = members;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the identifier of this action group.
|
||||||
|
*
|
||||||
|
* @return action group identifier
|
||||||
|
*/
|
||||||
|
public PiActionGroupId id() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type of this action group.
|
||||||
|
*
|
||||||
|
* @return action group type
|
||||||
|
*/
|
||||||
|
public Type type() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the members of this action group.
|
||||||
|
*
|
||||||
|
* @return collection of action members.
|
||||||
|
*/
|
||||||
|
public Collection<PiActionGroupMember> members() {
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PiActionGroup that = (PiActionGroup) o;
|
||||||
|
return id == that.id &&
|
||||||
|
Objects.equal(type, that.type) &&
|
||||||
|
Objects.equal(members, that.members);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(id, type, members);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return MoreObjects.toStringHelper(this)
|
||||||
|
.add("groupId", id)
|
||||||
|
.add("type", type)
|
||||||
|
.add("members", members)
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new builder of action groups.
|
||||||
|
*
|
||||||
|
* @return action group builder
|
||||||
|
*/
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder of action groups.
|
||||||
|
*/
|
||||||
|
public static final class Builder {
|
||||||
|
|
||||||
|
private PiActionGroupId id;
|
||||||
|
private Type type;
|
||||||
|
private Map<PiActionGroupMemberId, PiActionGroupMember> members = Maps.newHashMap();
|
||||||
|
|
||||||
|
private Builder() {
|
||||||
|
// hides constructor.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the identifier of this action group.
|
||||||
|
*
|
||||||
|
* @param id action group identifier
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public Builder withId(PiActionGroupId id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the type of this action group.
|
||||||
|
*
|
||||||
|
* @param type action group type
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public Builder withType(Type type) {
|
||||||
|
this.type = type;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds one member to this action group.
|
||||||
|
*
|
||||||
|
* @param member action group member
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public Builder addMember(PiActionGroupMember member) {
|
||||||
|
members.put(member.id(), member);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds many members to this action group.
|
||||||
|
*
|
||||||
|
* @param members action group members
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public Builder addMembers(Collection<PiActionGroupMember> members) {
|
||||||
|
members.forEach(this::addMember);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new action group.
|
||||||
|
*
|
||||||
|
* @return action group
|
||||||
|
*/
|
||||||
|
public PiActionGroup build() {
|
||||||
|
checkNotNull(id);
|
||||||
|
checkNotNull(type);
|
||||||
|
checkArgument(members.size() > 0, "Members cannot be empty");
|
||||||
|
return new PiActionGroup(id, type, ImmutableSet.copyOf(members.values()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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.net.pi.runtime;
|
||||||
|
|
||||||
|
import com.google.common.annotations.Beta;
|
||||||
|
import org.onlab.util.Identifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifier of an action group in a protocol-independent pipeline.
|
||||||
|
*/
|
||||||
|
@Beta
|
||||||
|
public final class PiActionGroupId extends Identifier<Integer> implements PiTableAction {
|
||||||
|
|
||||||
|
private PiActionGroupId(int id) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an action group identifier for the given integer value.
|
||||||
|
*
|
||||||
|
* @param id identifier
|
||||||
|
* @return action group
|
||||||
|
*/
|
||||||
|
public static PiActionGroupId of(int id) {
|
||||||
|
return new PiActionGroupId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
In P4Runtime, groups can be referenced directly as table actions (i.e. without invoking the selector).
|
||||||
|
In future we should consider having a more appropriate wrapper class for group IDs, instead of implementing
|
||||||
|
the PiTableAction interface.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Type type() {
|
||||||
|
return Type.ACTION_GROUP_ID;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* 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.net.pi.runtime;
|
||||||
|
|
||||||
|
import com.google.common.annotations.Beta;
|
||||||
|
import com.google.common.base.MoreObjects;
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Member of an action group in a protocol-independent pipeline.
|
||||||
|
*/
|
||||||
|
@Beta
|
||||||
|
public final class PiActionGroupMember {
|
||||||
|
|
||||||
|
private final PiActionGroupMemberId id;
|
||||||
|
private final PiAction action;
|
||||||
|
private final int weight;
|
||||||
|
|
||||||
|
private PiActionGroupMember(PiActionGroupMemberId id, PiAction action, int weight) {
|
||||||
|
this.id = id;
|
||||||
|
this.action = action;
|
||||||
|
this.weight = weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the identifier of this member.
|
||||||
|
*
|
||||||
|
* @return member identifier
|
||||||
|
*/
|
||||||
|
public PiActionGroupMemberId id() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the action associated to this member.
|
||||||
|
*
|
||||||
|
* @return action
|
||||||
|
*/
|
||||||
|
public PiAction action() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the weight associated to this member. Valid if the action group is of type {@link
|
||||||
|
* PiActionGroup.Type#SELECT}.
|
||||||
|
*
|
||||||
|
* @return weight
|
||||||
|
*/
|
||||||
|
public int weight() {
|
||||||
|
return weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(o instanceof PiActionGroupMember)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PiActionGroupMember that = (PiActionGroupMember) o;
|
||||||
|
return weight == that.weight &&
|
||||||
|
Objects.equal(id, that.id) &&
|
||||||
|
Objects.equal(action, that.action);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(id, action, weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return MoreObjects.toStringHelper(this)
|
||||||
|
.add("id", id)
|
||||||
|
.add("action", action)
|
||||||
|
.add("weight", weight)
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new builder of action group members.
|
||||||
|
*
|
||||||
|
* @return member builder
|
||||||
|
*/
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder of action group members.
|
||||||
|
*/
|
||||||
|
public static final class Builder {
|
||||||
|
|
||||||
|
private PiActionGroupMemberId id;
|
||||||
|
private PiAction action;
|
||||||
|
private int weight;
|
||||||
|
|
||||||
|
private Builder() {
|
||||||
|
// Hides constructor.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the identifier of this member.
|
||||||
|
*
|
||||||
|
* @param id member identifier
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public Builder withId(PiActionGroupMemberId id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the action of this member.
|
||||||
|
*
|
||||||
|
* @param action action
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public Builder withAction(PiAction action) {
|
||||||
|
this.action = action;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the weight of this member. Valid if the action group is of type {@link PiActionGroup.Type#SELECT}.
|
||||||
|
* <p>
|
||||||
|
* Default value is 0.
|
||||||
|
*
|
||||||
|
* @param weight weight
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public Builder withWeight(int weight) {
|
||||||
|
this.weight = weight;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new action group member.
|
||||||
|
*
|
||||||
|
* @return action group member
|
||||||
|
*/
|
||||||
|
public PiActionGroupMember build() {
|
||||||
|
checkNotNull(id);
|
||||||
|
checkNotNull(action);
|
||||||
|
return new PiActionGroupMember(id, action, weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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.net.pi.runtime;
|
||||||
|
|
||||||
|
import com.google.common.annotations.Beta;
|
||||||
|
import org.onlab.util.Identifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifier of a member of an action group in a protocol-independent pipeline.
|
||||||
|
*/
|
||||||
|
@Beta
|
||||||
|
public final class PiActionGroupMemberId extends Identifier<Integer> implements PiTableAction {
|
||||||
|
|
||||||
|
private PiActionGroupMemberId(int id) {
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an action group identifier for the given integer value.
|
||||||
|
*
|
||||||
|
* @param id identifier
|
||||||
|
* @return action group
|
||||||
|
*/
|
||||||
|
public static PiActionGroupMemberId of(int id) {
|
||||||
|
return new PiActionGroupMemberId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
In P4Runtime, group members can be referenced directly as table actions.
|
||||||
|
In future we should consider having a more appropriate wrapper class for group member IDs, instead of implementing
|
||||||
|
the PiTableAction interface.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Type type() {
|
||||||
|
return Type.GROUP_MEMBER_ID;
|
||||||
|
}
|
||||||
|
}
|
@ -38,15 +38,14 @@ public interface PiTableAction {
|
|||||||
*/
|
*/
|
||||||
ACTION,
|
ACTION,
|
||||||
|
|
||||||
// TODO: in P4Runtime a table action can be any of the following 3.
|
/**
|
||||||
// How to represent action profiles?
|
* Executes the action group specified by the given identifier.
|
||||||
/* message TableAction {
|
|
||||||
oneof type {
|
|
||||||
Action action = 1;
|
|
||||||
uint32 action_profile_member_id = 2;
|
|
||||||
uint32 action_profile_group_id = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
|
ACTION_GROUP_ID,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the action member group specified by the given identifier.
|
||||||
|
*/
|
||||||
|
GROUP_MEMBER_ID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* 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.drivers.bmv2;
|
||||||
|
|
||||||
|
import org.onosproject.net.Device;
|
||||||
|
import org.onosproject.net.DeviceId;
|
||||||
|
import org.onosproject.net.driver.AbstractHandlerBehaviour;
|
||||||
|
import org.onosproject.net.group.GroupBucket;
|
||||||
|
import org.onosproject.net.group.GroupDescription;
|
||||||
|
import org.onosproject.net.group.GroupOperation;
|
||||||
|
import org.onosproject.net.group.GroupOperations;
|
||||||
|
import org.onosproject.net.group.GroupProgrammable;
|
||||||
|
import org.onosproject.net.pi.model.PiPipelineInterpreter;
|
||||||
|
import org.onosproject.net.pi.runtime.PiAction;
|
||||||
|
import org.onosproject.net.pi.runtime.PiActionGroup;
|
||||||
|
import org.onosproject.net.pi.runtime.PiActionGroupId;
|
||||||
|
import org.onosproject.net.pi.runtime.PiActionGroupMember;
|
||||||
|
import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
|
||||||
|
import org.onosproject.net.pi.runtime.PiTableId;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class Bmv2GroupProgrammable extends AbstractHandlerBehaviour implements GroupProgrammable {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Work in progress.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private Device device;
|
||||||
|
|
||||||
|
/*
|
||||||
|
About action groups in P4runtime:
|
||||||
|
The type field is a place holder in p4runtime.proto right now, and we haven't defined it yet. You can assume all
|
||||||
|
the groups are "select" as per the OF spec. As a remainder, in the P4 terminology a member corresponds to an OF
|
||||||
|
bucket. Each member can also be used directly in the match table (kind of like an OF indirect group).
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void performGroupOperation(DeviceId deviceId, GroupOperations groupOps) {
|
||||||
|
|
||||||
|
for (GroupOperation groupOp : groupOps.operations()) {
|
||||||
|
switch (groupOp.opType()) {
|
||||||
|
case ADD:
|
||||||
|
addGroup(deviceId, groupOp);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addGroup(DeviceId deviceId, GroupOperation groupOp) {
|
||||||
|
|
||||||
|
// Most of this logic can go in a core service, e.g. PiGroupTranslationService
|
||||||
|
|
||||||
|
// From a P4Runtime perspective, we need first to insert members, then the group.
|
||||||
|
|
||||||
|
PiActionGroupId piActionGroupId = PiActionGroupId.of(groupOp.groupId().id());
|
||||||
|
|
||||||
|
PiActionGroup.Builder piActionGroupBuilder = PiActionGroup.builder()
|
||||||
|
.withId(piActionGroupId)
|
||||||
|
.withType(PiActionGroup.Type.SELECT);
|
||||||
|
|
||||||
|
if (groupOp.groupType() != GroupDescription.Type.SELECT) {
|
||||||
|
// log error
|
||||||
|
}
|
||||||
|
|
||||||
|
int bucketIdx = 0;
|
||||||
|
for (GroupBucket bucket : groupOp.buckets().buckets()) {
|
||||||
|
/*
|
||||||
|
Problem:
|
||||||
|
In P4Runtime action group members, i.e. action buckets, are associated to a numeric ID chosen
|
||||||
|
at member insertion time. This ID must be unique for the whole action profile (i.e. the group table in
|
||||||
|
OpenFlow). In ONOS, GroupBucket doesn't specify any ID.
|
||||||
|
|
||||||
|
Solutions:
|
||||||
|
- Change GroupBucket API to force application wanting to perform group operations to specify a member id.
|
||||||
|
- Maintain state to dynamically allocate/deallocate member IDs, e.g. in a dedicated service, or in a
|
||||||
|
P4Runtime Group Provider.
|
||||||
|
|
||||||
|
Hack:
|
||||||
|
Statically derive member ID by combining groupId and position of the bucket in the list.
|
||||||
|
*/
|
||||||
|
int memberId = ByteBuffer.allocate(4)
|
||||||
|
.putShort((short) (piActionGroupId.id() % 2 ^ 16))
|
||||||
|
.putShort((short) (bucketIdx % 2 ^ 16))
|
||||||
|
.getInt();
|
||||||
|
|
||||||
|
// Need an interpreter to map the bucket treatment to a PI action
|
||||||
|
|
||||||
|
if (!device.is(PiPipelineInterpreter.class)) {
|
||||||
|
// log error
|
||||||
|
}
|
||||||
|
|
||||||
|
PiPipelineInterpreter interpreter = device.as(PiPipelineInterpreter.class);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Problem:
|
||||||
|
In P4Runtime, action profiles (i.e. group tables) are specific to one or more tables.
|
||||||
|
Mapping of treatments depends on the target table. How do we derive the target table from here?
|
||||||
|
|
||||||
|
Solution:
|
||||||
|
- Change GroupDescription to allow applications to specify a table where this group will be called from.
|
||||||
|
|
||||||
|
Hack:
|
||||||
|
Assume we support pipelines with only one action profile associated to only one table, i.e. derive the
|
||||||
|
table ID by looking at the P4Info.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PiTableId piTableId = PiTableId.of("derive from P4Info");
|
||||||
|
|
||||||
|
|
||||||
|
PiAction action = null;
|
||||||
|
try {
|
||||||
|
action = interpreter.mapTreatment(bucket.treatment(), piTableId);
|
||||||
|
} catch (PiPipelineInterpreter.PiInterpreterException e) {
|
||||||
|
// log error
|
||||||
|
}
|
||||||
|
|
||||||
|
PiActionGroupMember member = PiActionGroupMember.builder()
|
||||||
|
.withId(PiActionGroupMemberId.of(memberId))
|
||||||
|
.withAction(action)
|
||||||
|
.withWeight(bucket.weight())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
piActionGroupBuilder.addMember(member);
|
||||||
|
|
||||||
|
// Use P4RuntimeClient to install member;
|
||||||
|
// TODO: implement P4RuntimeClient method.
|
||||||
|
}
|
||||||
|
|
||||||
|
PiActionGroup piActionGroup = piActionGroupBuilder.build();
|
||||||
|
|
||||||
|
// Use P4RuntimeClient to insert group.
|
||||||
|
// TODO: implement P4RuntimeClient method.
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
1
drivers/bmv2/src/main/resources/default.json
Symbolic link
1
drivers/bmv2/src/main/resources/default.json
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../tools/test/p4src/p4-16/p4c-out/default.json
|
@ -1,113 +0,0 @@
|
|||||||
tables {
|
|
||||||
preamble {
|
|
||||||
id: 33617813
|
|
||||||
name: "table0"
|
|
||||||
alias: "table0"
|
|
||||||
}
|
|
||||||
match_fields {
|
|
||||||
id: 1
|
|
||||||
name: "standard_metadata.ingress_port"
|
|
||||||
bitwidth: 9
|
|
||||||
match_type: TERNARY
|
|
||||||
}
|
|
||||||
match_fields {
|
|
||||||
id: 2
|
|
||||||
name: "hdr.ethernet.dstAddr"
|
|
||||||
bitwidth: 48
|
|
||||||
match_type: TERNARY
|
|
||||||
}
|
|
||||||
match_fields {
|
|
||||||
id: 3
|
|
||||||
name: "hdr.ethernet.srcAddr"
|
|
||||||
bitwidth: 48
|
|
||||||
match_type: TERNARY
|
|
||||||
}
|
|
||||||
match_fields {
|
|
||||||
id: 4
|
|
||||||
name: "hdr.ethernet.etherType"
|
|
||||||
bitwidth: 16
|
|
||||||
match_type: TERNARY
|
|
||||||
}
|
|
||||||
action_refs {
|
|
||||||
id: 16794308
|
|
||||||
}
|
|
||||||
action_refs {
|
|
||||||
id: 16829080
|
|
||||||
}
|
|
||||||
action_refs {
|
|
||||||
id: 16793508
|
|
||||||
}
|
|
||||||
action_refs {
|
|
||||||
id: 16800567
|
|
||||||
annotations: "@defaultonly()"
|
|
||||||
}
|
|
||||||
direct_resource_ids: 301990488
|
|
||||||
size: 1024
|
|
||||||
with_entry_timeout: true
|
|
||||||
}
|
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16794308
|
|
||||||
name: "set_egress_port"
|
|
||||||
alias: "set_egress_port"
|
|
||||||
}
|
|
||||||
params {
|
|
||||||
id: 1
|
|
||||||
name: "port"
|
|
||||||
bitwidth: 9
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16829080
|
|
||||||
name: "send_to_cpu"
|
|
||||||
alias: "send_to_cpu"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16793508
|
|
||||||
name: "drop"
|
|
||||||
alias: "drop"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actions {
|
|
||||||
preamble {
|
|
||||||
id: 16800567
|
|
||||||
name: "NoAction"
|
|
||||||
alias: "NoAction"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
counters {
|
|
||||||
preamble {
|
|
||||||
id: 302025528
|
|
||||||
name: "port_counters_control.egress_port_counter"
|
|
||||||
alias: "egress_port_counter"
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
unit: PACKETS
|
|
||||||
}
|
|
||||||
size: 254
|
|
||||||
}
|
|
||||||
counters {
|
|
||||||
preamble {
|
|
||||||
id: 301999025
|
|
||||||
name: "port_counters_control.ingress_port_counter"
|
|
||||||
alias: "ingress_port_counter"
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
unit: PACKETS
|
|
||||||
}
|
|
||||||
size: 254
|
|
||||||
}
|
|
||||||
direct_counters {
|
|
||||||
preamble {
|
|
||||||
id: 301990488
|
|
||||||
name: "table0_counter"
|
|
||||||
alias: "table0_counter"
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
unit: PACKETS
|
|
||||||
}
|
|
||||||
direct_table_id: 33617813
|
|
||||||
}
|
|
1
drivers/bmv2/src/main/resources/default.p4info
Symbolic link
1
drivers/bmv2/src/main/resources/default.p4info
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../tools/test/p4src/p4-16/p4c-out/default.p4info
|
@ -349,6 +349,24 @@ public final class P4RuntimeClientImpl implements P4RuntimeClient {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the internal P4 device ID associated with this client.
|
||||||
|
*
|
||||||
|
* @return P4 device ID
|
||||||
|
*/
|
||||||
|
public int p4DeviceId() {
|
||||||
|
return p4DeviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For testing purpose only. TODO: remove before release.
|
||||||
|
*
|
||||||
|
* @return blocking stub
|
||||||
|
*/
|
||||||
|
public P4RuntimeGrpc.P4RuntimeBlockingStub blockingStub() {
|
||||||
|
return this.blockingStub;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
@ -11,21 +11,32 @@
|
|||||||
control ingress(inout headers_t hdr, inout metadata_t meta, inout standard_metadata_t standard_metadata) {
|
control ingress(inout headers_t hdr, inout metadata_t meta, inout standard_metadata_t standard_metadata) {
|
||||||
|
|
||||||
direct_counter(CounterType.packets) table0_counter;
|
direct_counter(CounterType.packets) table0_counter;
|
||||||
|
action_selector(HashAlgorithm.crc16, 32w64, 32w16) ecmp_selector;
|
||||||
|
|
||||||
table table0 {
|
table table0 {
|
||||||
support_timeout = true;
|
support_timeout = true;
|
||||||
actions = {
|
|
||||||
set_egress_port(standard_metadata);
|
|
||||||
send_to_cpu(standard_metadata);
|
|
||||||
drop(standard_metadata);
|
|
||||||
}
|
|
||||||
key = {
|
key = {
|
||||||
standard_metadata.ingress_port : ternary;
|
standard_metadata.ingress_port : ternary;
|
||||||
hdr.ethernet.dstAddr : ternary;
|
hdr.ethernet.dstAddr : ternary;
|
||||||
hdr.ethernet.srcAddr : ternary;
|
hdr.ethernet.srcAddr : ternary;
|
||||||
hdr.ethernet.etherType : ternary;
|
hdr.ethernet.etherType : ternary;
|
||||||
|
// Not for matching.
|
||||||
|
// Inputs to the hash function of the action selector.
|
||||||
|
hdr.ipv4.srcAddr : selector;
|
||||||
|
hdr.ipv4.dstAddr : selector;
|
||||||
|
hdr.ipv4.protocol : selector;
|
||||||
|
hdr.tcp.srcPort : selector;
|
||||||
|
hdr.tcp.dstPort : selector;
|
||||||
|
hdr.udp.srcPort : selector;
|
||||||
|
hdr.udp.dstPort : selector;
|
||||||
|
}
|
||||||
|
actions = {
|
||||||
|
set_egress_port(standard_metadata);
|
||||||
|
send_to_cpu(standard_metadata);
|
||||||
|
drop(standard_metadata);
|
||||||
}
|
}
|
||||||
counters = table0_counter;
|
counters = table0_counter;
|
||||||
|
implementation = ecmp_selector;
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketIoIngressControl() packet_io_ingress_control;
|
PacketIoIngressControl() packet_io_ingress_control;
|
||||||
|
2
tools/test/p4src/p4-16/p4c-out/.gitignore
vendored
2
tools/test/p4src/p4-16/p4c-out/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
*.json
|
|
||||||
*.p4info
|
|
File diff suppressed because it is too large
Load Diff
@ -41,6 +41,7 @@ tables {
|
|||||||
id: 16800567
|
id: 16800567
|
||||||
annotations: "@defaultonly()"
|
annotations: "@defaultonly()"
|
||||||
}
|
}
|
||||||
|
implementation_id: 285227860
|
||||||
direct_resource_ids: 301990488
|
direct_resource_ids: 301990488
|
||||||
size: 1024
|
size: 1024
|
||||||
with_entry_timeout: true
|
with_entry_timeout: true
|
||||||
@ -78,6 +79,16 @@ actions {
|
|||||||
alias: "NoAction"
|
alias: "NoAction"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
action_profiles {
|
||||||
|
preamble {
|
||||||
|
id: 285227860
|
||||||
|
name: "ecmp_selector"
|
||||||
|
alias: "ecmp_selector"
|
||||||
|
}
|
||||||
|
table_ids: 33617813
|
||||||
|
with_selector: true
|
||||||
|
size: 64
|
||||||
|
}
|
||||||
counters {
|
counters {
|
||||||
preamble {
|
preamble {
|
||||||
id: 302025528
|
id: 302025528
|
||||||
@ -122,11 +133,6 @@ controller_packet_metadata {
|
|||||||
name: "ingress_port"
|
name: "ingress_port"
|
||||||
bitwidth: 9
|
bitwidth: 9
|
||||||
}
|
}
|
||||||
metadata {
|
|
||||||
id: 2
|
|
||||||
name: "other1"
|
|
||||||
bitwidth: 32
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
controller_packet_metadata {
|
controller_packet_metadata {
|
||||||
preamble {
|
preamble {
|
||||||
@ -139,9 +145,4 @@ controller_packet_metadata {
|
|||||||
name: "egress_port"
|
name: "egress_port"
|
||||||
bitwidth: 9
|
bitwidth: 9
|
||||||
}
|
}
|
||||||
metadata {
|
|
||||||
id: 2
|
|
||||||
name: "other2"
|
|
||||||
bitwidth: 32
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user