blob: 74e6845b17462e734aa29f6ceeab0cb2cb77d573 [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 Casconea62ac3d2017-08-30 03:19:00 +020026import org.onosproject.drivers.bmv2.Bmv2DefaultPipeconfFactory;
Carmelo Casconec8e84982017-07-26 15:34:42 -040027import org.onosproject.grpc.ctl.GrpcControllerImpl;
28import org.onosproject.net.DeviceId;
Carmelo Casconec8e84982017-07-26 15:34:42 -040029import org.onosproject.net.pi.model.PiPipeconf;
Carmelo Casconec8e84982017-07-26 15:34:42 -040030import org.onosproject.net.pi.model.PiPipelineInterpreter;
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +020031import org.onosproject.net.pi.runtime.PiAction;
32import org.onosproject.net.pi.runtime.PiActionId;
33import org.onosproject.net.pi.runtime.PiActionParam;
34import org.onosproject.net.pi.runtime.PiActionParamId;
35import org.onosproject.net.pi.runtime.PiHeaderFieldId;
36import org.onosproject.net.pi.runtime.PiMatchKey;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040037import org.onosproject.net.pi.runtime.PiPacketMetadata;
38import org.onosproject.net.pi.runtime.PiPacketMetadataId;
39import org.onosproject.net.pi.runtime.PiPacketOperation;
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +020040import org.onosproject.net.pi.runtime.PiTableEntry;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040041import org.onosproject.net.pi.runtime.PiTableId;
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +020042import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
43import org.onosproject.p4runtime.api.P4RuntimeClient;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040044import org.onosproject.p4runtime.ctl.P4RuntimeClientImpl;
Carmelo Casconec8e84982017-07-26 15:34:42 -040045import org.onosproject.p4runtime.ctl.P4RuntimeControllerImpl;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040046import p4.P4RuntimeGrpc;
47import p4.P4RuntimeOuterClass;
Carmelo Casconec8e84982017-07-26 15:34:42 -040048
49import java.net.URL;
50import java.util.concurrent.ExecutionException;
51
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +020052import static org.onlab.util.ImmutableByteSequence.*;
Carmelo Casconec8e84982017-07-26 15:34:42 -040053import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.BMV2_JSON;
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040054import static org.onosproject.net.pi.runtime.PiPacketOperation.Type.PACKET_OUT;
55import static p4.P4RuntimeOuterClass.ActionProfileGroup.Type.SELECT;
56import static p4.P4RuntimeOuterClass.Update.Type.INSERT;
Carmelo Casconec8e84982017-07-26 15:34:42 -040057
58/**
59 * Class used for quick testing of P4Runtime with real devices. To be removed before release.
60 */
61public class P4RuntimeTest {
62
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040063 private static final String GRPC_SERVER_ADDR = "192.168.56.102";
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +020064 private static final int GRPC_SERVER_PORT = 55044;
65
66 private static final String TABLE_0 = "table0";
67 private static final String SET_EGRESS_PORT = "set_egress_port";
68 private static final String PORT = "port";
69 private static final String ETHERNET = "ethernet";
70 private static final String DST_ADDR = "dstAddr";
71 private static final String SRC_ADDR = "srcAddr";
72 private static final String STANDARD_METADATA = "standard_metadata";
73 private static final String INGRESS_PORT = "ingress_port";
74 private static final String ETHER_TYPE = "etherType";
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040075
Andrea Campanella0288c872017-08-07 18:32:51 +020076
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040077 private final URL p4InfoUrl = this.getClass().getResource("/bmv2/default.p4info");
78 private final URL jsonUrl = this.getClass().getResource("/bmv2/default.json");
Carmelo Casconec8e84982017-07-26 15:34:42 -040079
Carmelo Casconea62ac3d2017-08-30 03:19:00 +020080 private final PiPipeconf bmv2DefaultPipeconf = Bmv2DefaultPipeconfFactory.get();
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -040081 private final P4RuntimeControllerImpl controller = new P4RuntimeControllerImpl();
82 private final GrpcControllerImpl grpcController = new GrpcControllerImpl();
83 private final DeviceId deviceId = DeviceId.deviceId("dummy:1");
84 private final ManagedChannelBuilder channelBuilder = NettyChannelBuilder
85 .forAddress(GRPC_SERVER_ADDR, GRPC_SERVER_PORT)
86 .usePlaintext(true);
87 private P4RuntimeClientImpl client;
Carmelo Casconec8e84982017-07-26 15:34:42 -040088
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +020089 private final ImmutableByteSequence ethAddr = fit(copyFrom(1), 48);
90 private final ImmutableByteSequence portValue = copyFrom((short) 1);
91 private final PiHeaderFieldId ethDstAddrFieldId = PiHeaderFieldId.of(ETHERNET, DST_ADDR);
92 private final PiHeaderFieldId ethSrcAddrFieldId = PiHeaderFieldId.of(ETHERNET, SRC_ADDR);
93 private final PiHeaderFieldId inPortFieldId = PiHeaderFieldId.of(STANDARD_METADATA, INGRESS_PORT);
94 private final PiHeaderFieldId ethTypeFieldId = PiHeaderFieldId.of(ETHERNET, ETHER_TYPE);
95 private final PiActionParamId portParamId = PiActionParamId.of(PORT);
96 private final PiActionId outActionId = PiActionId.of(SET_EGRESS_PORT);
97 private final PiTableId tableId = PiTableId.of(TABLE_0);
98
99 private final PiTableEntry piTableEntry = PiTableEntry
100 .builder()
101 .forTable(tableId)
102 .withMatchKey(PiMatchKey.builder()
103 .addFieldMatch(new PiTernaryFieldMatch(ethDstAddrFieldId, ethAddr, ofZeros(6)))
104 .addFieldMatch(new PiTernaryFieldMatch(ethSrcAddrFieldId, ethAddr, ofZeros(6)))
105 .addFieldMatch(new PiTernaryFieldMatch(inPortFieldId, portValue, ofZeros(2)))
106 .addFieldMatch(new PiTernaryFieldMatch(ethTypeFieldId, portValue, ofZeros(2)))
107 .build())
108 .withAction(PiAction
109 .builder()
110 .withId(outActionId)
111 .withParameter(new PiActionParam(portParamId, portValue))
112 .build())
113 .withPriority(1)
114 .withCookie(2)
115 .build();
116
117 public P4RuntimeTest() throws ImmutableByteSequence.ByteSequenceTrimException {
118 }
119
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400120 @Before
121 public void setUp() throws Exception {
Carmelo Casconec8e84982017-07-26 15:34:42 -0400122 controller.grpcController = grpcController;
123 GrpcControllerImpl.enableMessageLog = true;
124 grpcController.activate();
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400125 }
Carmelo Casconec8e84982017-07-26 15:34:42 -0400126
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200127 private void createClient()
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400128 throws ExecutionException, InterruptedException, PiPipelineInterpreter.PiInterpreterException,
129 IllegalAccessException, InstantiationException {
Carmelo Casconec8e84982017-07-26 15:34:42 -0400130
131 assert (controller.createClient(deviceId, 1, channelBuilder));
132
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400133 client = (P4RuntimeClientImpl) controller.getClient(deviceId);
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200134 }
135
136 private void setPipelineConfig(PiPipeconf pipeconf, PiPipeconf.ExtensionType extensionType)
137 throws ExecutionException, InterruptedException, PiPipelineInterpreter.PiInterpreterException,
138 IllegalAccessException, InstantiationException {
Carmelo Casconec8e84982017-07-26 15:34:42 -0400139
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400140 assert (client.setPipelineConfig(pipeconf, extensionType).get());
Carmelo Casconec8e84982017-07-26 15:34:42 -0400141 assert (client.initStreamChannel().get());
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400142 }
Carmelo Casconec8e84982017-07-26 15:34:42 -0400143
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400144 private void testActionProfile(int actionProfileId) {
145
146 P4RuntimeGrpc.P4RuntimeBlockingStub stub = client.blockingStub();
147
148 P4RuntimeOuterClass.ActionProfileMember profileMemberMsg = P4RuntimeOuterClass.ActionProfileMember.newBuilder()
149 .setActionProfileId(actionProfileId)
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200150 .setMemberId(1)
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400151 .setAction(P4RuntimeOuterClass.Action.newBuilder()
152 .setActionId(16793508)
153 .build())
154 .build();
155
156 P4RuntimeOuterClass.ActionProfileGroup groupMsg = P4RuntimeOuterClass.ActionProfileGroup.newBuilder()
157 .setActionProfileId(actionProfileId)
158 .setGroupId(1)
159 .setType(SELECT)
160 .addMembers(P4RuntimeOuterClass.ActionProfileGroup.Member.newBuilder()
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200161 .setMemberId(1)
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400162 .setWeight(1)
163 .build())
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200164 .setMaxSize(3)
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400165 .build();
166
167 P4RuntimeOuterClass.WriteRequest writeRequest = P4RuntimeOuterClass.WriteRequest.newBuilder()
168 .setDeviceId(client.p4DeviceId())
169 .addUpdates(P4RuntimeOuterClass.Update.newBuilder()
170 .setType(INSERT)
171 .setEntity(P4RuntimeOuterClass.Entity.newBuilder()
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200172 .setActionProfileGroup(groupMsg)
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400173 .build())
174 .build())
175 .addUpdates(P4RuntimeOuterClass.Update.newBuilder()
176 .setType(INSERT)
177 .setEntity(P4RuntimeOuterClass.Entity.newBuilder()
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200178 .setActionProfileMember(profileMemberMsg)
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400179 .build())
180 .build())
181 .build();
182
183 stub.write(writeRequest);
184 }
185
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200186 private void testPacketOut() throws IllegalAccessException, InstantiationException, ExecutionException,
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400187 InterruptedException, ImmutableByteSequence.ByteSequenceTrimException {
188
189 PiPacketOperation packetOperation = PiPacketOperation.builder()
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200190 .withData(fit(copyFrom(1), 48 + 48 + 16))
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400191 .withType(PACKET_OUT)
192 .withMetadata(PiPacketMetadata.builder()
193 .withId(PiPacketMetadataId.of("egress_port"))
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200194 .withValue(fit(copyFrom(255), 9))
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400195 .build())
196 .build();
197
198 assert (client.packetOut(packetOperation, bmv2DefaultPipeconf).get());
Carmelo Casconea966c342017-07-30 01:56:30 -0400199
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200200 Thread.sleep(5000);
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400201 }
202
203 private void testDumpTable(String tableName, PiPipeconf pipeconf) throws ExecutionException, InterruptedException {
204 assert (client.dumpTable(PiTableId.of(tableName), pipeconf).get().size() == 0);
205 }
206
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200207 private void testAddEntry(PiPipeconf pipeconf) throws ExecutionException, InterruptedException {
208 assert (client.writeTableEntries(Lists.newArrayList(piTableEntry), P4RuntimeClient.WriteOperationType.INSERT,
209 pipeconf).get());
210 }
211
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400212 @Test
213 @Ignore
214 public void testBmv2() throws Exception {
215
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200216 createClient();
217 setPipelineConfig(bmv2DefaultPipeconf, BMV2_JSON);
218 testPacketOut();
219
220 // testPacketOut();
221
222 // testActionProfile(285261835);
223 }
224
225 @Test
226 @Ignore
227 public void testBmv2AddEntry() throws Exception {
228 createClient();
229 testAddEntry(bmv2DefaultPipeconf);
230 testDumpTable(TABLE_0, bmv2DefaultPipeconf);
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400231 }
232
233 @Test
234 @Ignore
235 public void testTofino() throws Exception {
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200236 createClient();
237 setPipelineConfig(bmv2DefaultPipeconf, null);
Carmelo Casconeb2e3dba2017-07-27 12:07:09 -0400238 }
239
240// OLD STUFF
Carmelo Casconec8e84982017-07-26 15:34:42 -0400241// log.info("++++++++++++++++++++++++++++");
242//
243// PiPipelineInterpreter interpreter = (PiPipelineInterpreter) defaultPipeconf
244// .implementation(PiPipelineInterpreter.class)
245// .orElse(null)
246// .newInstance();
247//
248// TrafficTreatment t = DefaultTrafficTreatment.builder()
249// .setOutput(PortNumber.portNumber(830L)).build();
250// byte[] payload = new byte[1000];
251//// payload[0] = 1;
252// Arrays.fill( payload, (byte) 1 );
253//
254// OutboundPacket packet = new DefaultOutboundPacket(
255// deviceId, t, ByteBuffer.wrap(payload));
256//
257//
258// Collection<PiPacketOperation> operations = interpreter.mapOutboundPacket(packet,defaultPipeconf);
259// log.info("{}", operations);
260// operations.forEach(piPacketOperation -> {
261// try {
262// client.packetOut(piPacketOperation, defaultPipeconf).get();
263// } catch (InterruptedException | ExecutionException e) {
264// log.error("{}",e);
265// }
266// });
267
268// assert(client.dumpTable(PiTableId.of(TABLE_0), defaultPipeconf).get().size() == 0);
269
270// assert(client.writeTableEntries(Lists.newArrayList(piTableEntry), INSERT, defaultPipeconf).get());
271
272// assert(client.dumpTable(PiTableId.of(TABLE_0), defaultPipeconf).get().size() == 1);
Carmelo Casconec8e84982017-07-26 15:34:42 -0400273}