blob: c05e169ce8386e736ad23be81b79d4a1a8744cd1 [file] [log] [blame]
Carmelo Casconec8e84982017-07-26 15:34:42 -04001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Carmelo Casconec8e84982017-07-26 15:34:42 -04003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.p4runtime.test;
18
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +020019import com.google.common.collect.Lists;
Carmelo Casconec8e84982017-07-26 15:34:42 -040020import io.grpc.ManagedChannelBuilder;
21import io.grpc.netty.NettyChannelBuilder;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040022import org.junit.Before;
Carmelo Casconec8e84982017-07-26 15:34:42 -040023import org.junit.Ignore;
24import org.junit.Test;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040025import org.onlab.util.ImmutableByteSequence;
Carmelo Casconec8e84982017-07-26 15:34:42 -040026import org.onosproject.bmv2.model.Bmv2PipelineModelParser;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040027import org.onosproject.drivers.bmv2.Bmv2DefaultInterpreter;
Carmelo Casconec8e84982017-07-26 15:34:42 -040028import org.onosproject.grpc.ctl.GrpcControllerImpl;
29import org.onosproject.net.DeviceId;
30import org.onosproject.net.pi.model.DefaultPiPipeconf;
31import org.onosproject.net.pi.model.PiPipeconf;
32import org.onosproject.net.pi.model.PiPipeconfId;
33import org.onosproject.net.pi.model.PiPipelineInterpreter;
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +020034import org.onosproject.net.pi.runtime.PiAction;
35import org.onosproject.net.pi.runtime.PiActionId;
36import org.onosproject.net.pi.runtime.PiActionParam;
37import org.onosproject.net.pi.runtime.PiActionParamId;
38import org.onosproject.net.pi.runtime.PiHeaderFieldId;
39import org.onosproject.net.pi.runtime.PiMatchKey;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040040import org.onosproject.net.pi.runtime.PiPacketMetadata;
41import org.onosproject.net.pi.runtime.PiPacketMetadataId;
42import org.onosproject.net.pi.runtime.PiPacketOperation;
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +020043import org.onosproject.net.pi.runtime.PiTableEntry;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040044import org.onosproject.net.pi.runtime.PiTableId;
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +020045import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
46import org.onosproject.p4runtime.api.P4RuntimeClient;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040047import org.onosproject.p4runtime.ctl.P4RuntimeClientImpl;
Carmelo Casconec8e84982017-07-26 15:34:42 -040048import org.onosproject.p4runtime.ctl.P4RuntimeControllerImpl;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040049import p4.P4RuntimeGrpc;
50import p4.P4RuntimeOuterClass;
Carmelo Casconec8e84982017-07-26 15:34:42 -040051
52import java.net.URL;
53import java.util.concurrent.ExecutionException;
54
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +020055import static org.onlab.util.ImmutableByteSequence.*;
Carmelo Casconec8e84982017-07-26 15:34:42 -040056import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.BMV2_JSON;
57import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.P4_INFO_TEXT;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040058import static org.onosproject.net.pi.runtime.PiPacketOperation.Type.PACKET_OUT;
59import static p4.P4RuntimeOuterClass.ActionProfileGroup.Type.SELECT;
60import static p4.P4RuntimeOuterClass.Update.Type.INSERT;
Carmelo Casconec8e84982017-07-26 15:34:42 -040061
62/**
63 * Class used for quick testing of P4Runtime with real devices. To be removed before release.
64 */
65public class P4RuntimeTest {
66
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040067 private static final String GRPC_SERVER_ADDR = "192.168.56.102";
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +020068 private static final int GRPC_SERVER_PORT = 55044;
69
70 private static final String TABLE_0 = "table0";
71 private static final String SET_EGRESS_PORT = "set_egress_port";
72 private static final String PORT = "port";
73 private static final String ETHERNET = "ethernet";
74 private static final String DST_ADDR = "dstAddr";
75 private static final String SRC_ADDR = "srcAddr";
76 private static final String STANDARD_METADATA = "standard_metadata";
77 private static final String INGRESS_PORT = "ingress_port";
78 private static final String ETHER_TYPE = "etherType";
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040079
80 private final URL p4InfoUrl = this.getClass().getResource("/bmv2/default.p4info");
81 private final URL jsonUrl = this.getClass().getResource("/bmv2/default.json");
Carmelo Casconec8e84982017-07-26 15:34:42 -040082
83 private final PiPipeconf bmv2DefaultPipeconf = DefaultPiPipeconf.builder()
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040084 .withId(new PiPipeconfId("mock-bmv2"))
Carmelo Casconec8e84982017-07-26 15:34:42 -040085 .withPipelineModel(Bmv2PipelineModelParser.parse(jsonUrl))
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040086 .addBehaviour(PiPipelineInterpreter.class, Bmv2DefaultInterpreter.class)
Carmelo Casconec8e84982017-07-26 15:34:42 -040087 .addExtension(P4_INFO_TEXT, p4InfoUrl)
88 .addExtension(BMV2_JSON, jsonUrl)
89 .build();
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040090 private final P4RuntimeControllerImpl controller = new P4RuntimeControllerImpl();
91 private final GrpcControllerImpl grpcController = new GrpcControllerImpl();
92 private final DeviceId deviceId = DeviceId.deviceId("dummy:1");
93 private final ManagedChannelBuilder channelBuilder = NettyChannelBuilder
94 .forAddress(GRPC_SERVER_ADDR, GRPC_SERVER_PORT)
95 .usePlaintext(true);
96 private P4RuntimeClientImpl client;
Carmelo Casconec8e84982017-07-26 15:34:42 -040097
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +020098 private final ImmutableByteSequence ethAddr = fit(copyFrom(1), 48);
99 private final ImmutableByteSequence portValue = copyFrom((short) 1);
100 private final PiHeaderFieldId ethDstAddrFieldId = PiHeaderFieldId.of(ETHERNET, DST_ADDR);
101 private final PiHeaderFieldId ethSrcAddrFieldId = PiHeaderFieldId.of(ETHERNET, SRC_ADDR);
102 private final PiHeaderFieldId inPortFieldId = PiHeaderFieldId.of(STANDARD_METADATA, INGRESS_PORT);
103 private final PiHeaderFieldId ethTypeFieldId = PiHeaderFieldId.of(ETHERNET, ETHER_TYPE);
104 private final PiActionParamId portParamId = PiActionParamId.of(PORT);
105 private final PiActionId outActionId = PiActionId.of(SET_EGRESS_PORT);
106 private final PiTableId tableId = PiTableId.of(TABLE_0);
107
108 private final PiTableEntry piTableEntry = PiTableEntry
109 .builder()
110 .forTable(tableId)
111 .withMatchKey(PiMatchKey.builder()
112 .addFieldMatch(new PiTernaryFieldMatch(ethDstAddrFieldId, ethAddr, ofZeros(6)))
113 .addFieldMatch(new PiTernaryFieldMatch(ethSrcAddrFieldId, ethAddr, ofZeros(6)))
114 .addFieldMatch(new PiTernaryFieldMatch(inPortFieldId, portValue, ofZeros(2)))
115 .addFieldMatch(new PiTernaryFieldMatch(ethTypeFieldId, portValue, ofZeros(2)))
116 .build())
117 .withAction(PiAction
118 .builder()
119 .withId(outActionId)
120 .withParameter(new PiActionParam(portParamId, portValue))
121 .build())
122 .withPriority(1)
123 .withCookie(2)
124 .build();
125
126 public P4RuntimeTest() throws ImmutableByteSequence.ByteSequenceTrimException {
127 }
128
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400129 @Before
130 public void setUp() throws Exception {
Carmelo Casconec8e84982017-07-26 15:34:42 -0400131 controller.grpcController = grpcController;
132 GrpcControllerImpl.enableMessageLog = true;
133 grpcController.activate();
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400134 }
Carmelo Casconec8e84982017-07-26 15:34:42 -0400135
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200136 private void createClient()
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400137 throws ExecutionException, InterruptedException, PiPipelineInterpreter.PiInterpreterException,
138 IllegalAccessException, InstantiationException {
Carmelo Casconec8e84982017-07-26 15:34:42 -0400139
140 assert (controller.createClient(deviceId, 1, channelBuilder));
141
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400142 client = (P4RuntimeClientImpl) controller.getClient(deviceId);
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200143 }
144
145 private void setPipelineConfig(PiPipeconf pipeconf, PiPipeconf.ExtensionType extensionType)
146 throws ExecutionException, InterruptedException, PiPipelineInterpreter.PiInterpreterException,
147 IllegalAccessException, InstantiationException {
Carmelo Casconec8e84982017-07-26 15:34:42 -0400148
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400149 assert (client.setPipelineConfig(pipeconf, extensionType).get());
Carmelo Casconec8e84982017-07-26 15:34:42 -0400150 assert (client.initStreamChannel().get());
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400151 }
Carmelo Casconec8e84982017-07-26 15:34:42 -0400152
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400153 private void testActionProfile(int actionProfileId) {
154
155 P4RuntimeGrpc.P4RuntimeBlockingStub stub = client.blockingStub();
156
157 P4RuntimeOuterClass.ActionProfileMember profileMemberMsg = P4RuntimeOuterClass.ActionProfileMember.newBuilder()
158 .setActionProfileId(actionProfileId)
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200159 .setMemberId(1)
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400160 .setAction(P4RuntimeOuterClass.Action.newBuilder()
161 .setActionId(16793508)
162 .build())
163 .build();
164
165 P4RuntimeOuterClass.ActionProfileGroup groupMsg = P4RuntimeOuterClass.ActionProfileGroup.newBuilder()
166 .setActionProfileId(actionProfileId)
167 .setGroupId(1)
168 .setType(SELECT)
169 .addMembers(P4RuntimeOuterClass.ActionProfileGroup.Member.newBuilder()
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200170 .setMemberId(1)
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400171 .setWeight(1)
172 .build())
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200173 .setMaxSize(3)
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400174 .build();
175
176 P4RuntimeOuterClass.WriteRequest writeRequest = P4RuntimeOuterClass.WriteRequest.newBuilder()
177 .setDeviceId(client.p4DeviceId())
178 .addUpdates(P4RuntimeOuterClass.Update.newBuilder()
179 .setType(INSERT)
180 .setEntity(P4RuntimeOuterClass.Entity.newBuilder()
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200181 .setActionProfileGroup(groupMsg)
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400182 .build())
183 .build())
184 .addUpdates(P4RuntimeOuterClass.Update.newBuilder()
185 .setType(INSERT)
186 .setEntity(P4RuntimeOuterClass.Entity.newBuilder()
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200187 .setActionProfileMember(profileMemberMsg)
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400188 .build())
189 .build())
190 .build();
191
192 stub.write(writeRequest);
193 }
194
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200195 private void testPacketOut() throws IllegalAccessException, InstantiationException, ExecutionException,
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400196 InterruptedException, ImmutableByteSequence.ByteSequenceTrimException {
197
198 PiPacketOperation packetOperation = PiPacketOperation.builder()
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200199 .withData(fit(copyFrom(1), 48 + 48 + 16))
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400200 .withType(PACKET_OUT)
201 .withMetadata(PiPacketMetadata.builder()
202 .withId(PiPacketMetadataId.of("egress_port"))
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200203 .withValue(fit(copyFrom(255), 9))
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400204 .build())
205 .build();
206
207 assert (client.packetOut(packetOperation, bmv2DefaultPipeconf).get());
Carmelo Casconea966c342017-07-30 01:56:30 -0400208
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200209 Thread.sleep(5000);
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400210 }
211
212 private void testDumpTable(String tableName, PiPipeconf pipeconf) throws ExecutionException, InterruptedException {
213 assert (client.dumpTable(PiTableId.of(tableName), pipeconf).get().size() == 0);
214 }
215
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200216 private void testAddEntry(PiPipeconf pipeconf) throws ExecutionException, InterruptedException {
217 assert (client.writeTableEntries(Lists.newArrayList(piTableEntry), P4RuntimeClient.WriteOperationType.INSERT,
218 pipeconf).get());
219 }
220
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400221 @Test
222 @Ignore
223 public void testBmv2() throws Exception {
224
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200225 createClient();
226 setPipelineConfig(bmv2DefaultPipeconf, BMV2_JSON);
227 testPacketOut();
228
229 // testPacketOut();
230
231 // testActionProfile(285261835);
232 }
233
234 @Test
235 @Ignore
236 public void testBmv2AddEntry() throws Exception {
237 createClient();
238 testAddEntry(bmv2DefaultPipeconf);
239 testDumpTable(TABLE_0, bmv2DefaultPipeconf);
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400240 }
241
242 @Test
243 @Ignore
244 public void testTofino() throws Exception {
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200245 createClient();
246 setPipelineConfig(bmv2DefaultPipeconf, null);
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400247 }
248
249// OLD STUFF
Carmelo Casconec8e84982017-07-26 15:34:42 -0400250// log.info("++++++++++++++++++++++++++++");
251//
252// PiPipelineInterpreter interpreter = (PiPipelineInterpreter) defaultPipeconf
253// .implementation(PiPipelineInterpreter.class)
254// .orElse(null)
255// .newInstance();
256//
257// TrafficTreatment t = DefaultTrafficTreatment.builder()
258// .setOutput(PortNumber.portNumber(830L)).build();
259// byte[] payload = new byte[1000];
260//// payload[0] = 1;
261// Arrays.fill( payload, (byte) 1 );
262//
263// OutboundPacket packet = new DefaultOutboundPacket(
264// deviceId, t, ByteBuffer.wrap(payload));
265//
266//
267// Collection<PiPacketOperation> operations = interpreter.mapOutboundPacket(packet,defaultPipeconf);
268// log.info("{}", operations);
269// operations.forEach(piPacketOperation -> {
270// try {
271// client.packetOut(piPacketOperation, defaultPipeconf).get();
272// } catch (InterruptedException | ExecutionException e) {
273// log.error("{}",e);
274// }
275// });
276
277// assert(client.dumpTable(PiTableId.of(TABLE_0), defaultPipeconf).get().size() == 0);
278
279// assert(client.writeTableEntries(Lists.newArrayList(piTableEntry), INSERT, defaultPipeconf).get());
280
281// assert(client.dumpTable(PiTableId.of(TABLE_0), defaultPipeconf).get().size() == 1);
Carmelo Casconec8e84982017-07-26 15:34:42 -0400282}