blob: daeb62f2b2cab274c4bc0a036bbc6e4fe586892d [file] [log] [blame]
Carmelo Cascone8d99b172017-07-18 17:26:31 -04001/*
2 * Copyright 2017-present Open Networking Laboratory
3 *
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.ctl;
18
19import com.google.common.collect.Lists;
20import com.google.common.testing.EqualsTester;
21import org.junit.Test;
22import org.onlab.util.ImmutableByteSequence;
23import org.onosproject.bmv2.model.Bmv2PipelineModelParser;
24import org.onosproject.net.pi.model.DefaultPiPipeconf;
25import org.onosproject.net.pi.model.PiPipeconf;
26import org.onosproject.net.pi.model.PiPipeconfId;
27import org.onosproject.net.pi.runtime.PiAction;
28import org.onosproject.net.pi.runtime.PiActionId;
29import org.onosproject.net.pi.runtime.PiActionParam;
30import org.onosproject.net.pi.runtime.PiActionParamId;
31import org.onosproject.net.pi.runtime.PiHeaderFieldId;
32import org.onosproject.net.pi.runtime.PiTableEntry;
33import org.onosproject.net.pi.runtime.PiTableId;
34import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
35import p4.P4RuntimeOuterClass.Action;
36import p4.P4RuntimeOuterClass.TableEntry;
37
38import java.net.URL;
39import java.util.Collection;
40import java.util.Random;
41
42import static org.hamcrest.MatcherAssert.assertThat;
43import static org.hamcrest.Matchers.hasSize;
44import static org.hamcrest.Matchers.is;
45import static org.onlab.util.ImmutableByteSequence.copyFrom;
46import static org.onlab.util.ImmutableByteSequence.fit;
47import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.BMV2_JSON;
48import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.P4_INFO_TEXT;
49import static org.onosproject.p4runtime.ctl.TableEntryEncoder.decode;
50import static org.onosproject.p4runtime.ctl.TableEntryEncoder.encode;
51
52public class TableEntryEncoderTest {
53
54 private static final String TABLE_0 = "table0";
55 private static final String SET_EGRESS_PORT = "set_egress_port";
56 private static final String PORT = "port";
57 private static final String ETHERNET = "ethernet";
58 private static final String DST_ADDR = "dstAddr";
59 private static final String SRC_ADDR = "srcAddr";
60 private static final String STANDARD_METADATA = "standard_metadata";
61 private static final String INGRESS_PORT = "ingress_port";
62 private static final String ETHER_TYPE = "etherType";
63
64 private final Random rand = new Random();
65 private final URL p4InfoUrl = this.getClass().getResource("/default.p4info");
66 private final URL jsonUrl = this.getClass().getResource("/default.json");
67
68 private final PiPipeconf defaultPipeconf = DefaultPiPipeconf.builder()
69 .withId(new PiPipeconfId("mock"))
70 .withPipelineModel(Bmv2PipelineModelParser.parse(jsonUrl))
71 .addExtension(P4_INFO_TEXT, p4InfoUrl)
72 .addExtension(BMV2_JSON, jsonUrl)
73 .build();
74
75 private final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(defaultPipeconf);
76 private final ImmutableByteSequence ethAddr = fit(copyFrom(rand.nextInt()), 48);
77 private final ImmutableByteSequence portValue = copyFrom((short) rand.nextInt());
78 private final PiHeaderFieldId ethDstAddrFieldId = PiHeaderFieldId.of(ETHERNET, DST_ADDR);
79 private final PiHeaderFieldId ethSrcAddrFieldId = PiHeaderFieldId.of(ETHERNET, SRC_ADDR);
80 private final PiHeaderFieldId inPortFieldId = PiHeaderFieldId.of(STANDARD_METADATA, INGRESS_PORT);
81 private final PiHeaderFieldId ethTypeFieldId = PiHeaderFieldId.of(ETHERNET, ETHER_TYPE);
82 private final PiActionParamId portParamId = PiActionParamId.of(PORT);
83 private final PiActionId outActionId = PiActionId.of(SET_EGRESS_PORT);
84 private final PiTableId tableId = PiTableId.of(TABLE_0);
85
86 private final PiTableEntry piTableEntry = PiTableEntry
87 .builder()
88 .forTable(tableId)
89 .withFieldMatch(new PiTernaryFieldMatch(ethDstAddrFieldId, ethAddr, ImmutableByteSequence.ofOnes(6)))
90 .withFieldMatch(new PiTernaryFieldMatch(ethSrcAddrFieldId, ethAddr, ImmutableByteSequence.ofOnes(6)))
91 .withFieldMatch(new PiTernaryFieldMatch(inPortFieldId, portValue, ImmutableByteSequence.ofOnes(2)))
92 .withFieldMatch(new PiTernaryFieldMatch(ethTypeFieldId, portValue, ImmutableByteSequence.ofOnes(2)))
93 .withAction(PiAction
94 .builder()
95 .withId(outActionId)
96 .withParameter(new PiActionParam(portParamId, portValue))
97 .build())
98 .withPriority(1)
99 .withCookie(2)
100 .build();
101
102 public TableEntryEncoderTest() throws ImmutableByteSequence.ByteSequenceTrimException {
103 }
104
105 @Test
106 public void testP4InfoBrowser() throws Exception {
107
108 P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(defaultPipeconf);
109
110 assertThat(browser.tables().hasName(TABLE_0), is(true));
111 assertThat(browser.actions().hasName(SET_EGRESS_PORT), is(true));
112
113 int tableId = browser.tables().getByName(TABLE_0).getPreamble().getId();
114 int actionId = browser.actions().getByName(SET_EGRESS_PORT).getPreamble().getId();
115
116 assertThat(browser.matchFields(tableId).hasName(STANDARD_METADATA + "." + INGRESS_PORT), is(true));
117 assertThat(browser.actionParams(actionId).hasName(PORT), is(true));
118
119 // TODO: improve, assert browsing other entities (counters, meters, etc.)
120 }
121
122 @Test
123 public void testTableEntryEncoder()
124 throws P4InfoBrowser.NotFoundException, ImmutableByteSequence.ByteSequenceTrimException {
125
126 Collection<TableEntry> result = encode(Lists.newArrayList(piTableEntry), defaultPipeconf);
127 assertThat(result, hasSize(1));
128
129 TableEntry tableEntryMsg = result.iterator().next();
130
131 Collection<PiTableEntry> decodedResults = decode(Lists.newArrayList(tableEntryMsg), defaultPipeconf);
132 PiTableEntry decodedPiTableEntry = decodedResults.iterator().next();
133
134 // Test equality for decoded entry.
135 new EqualsTester()
136 .addEqualityGroup(piTableEntry, decodedPiTableEntry)
137 .testEquals();
138
139 // Table ID.
140 int p4InfoTableId = browser.tables().getByName(tableId.id()).getPreamble().getId();
141 int encodedTableId = tableEntryMsg.getTableId();
142 assertThat(encodedTableId, is(p4InfoTableId));
143
144 // Ternary match.
145 byte[] encodedTernaryMatchValue = tableEntryMsg.getMatch(0).getTernary().getValue().toByteArray();
146 assertThat(encodedTernaryMatchValue, is(ethAddr.asArray()));
147
148 Action actionMsg = tableEntryMsg.getAction().getAction();
149
150 // Action ID.
151 int p4InfoActionId = browser.actions().getByName(outActionId.name()).getPreamble().getId();
152 int encodedActionId = actionMsg.getActionId();
153 assertThat(encodedActionId, is(p4InfoActionId));
154
155 // Action param ID.
156 int p4InfoActionParamId = browser.actionParams(p4InfoActionId).getByName(portParamId.name()).getId();
157 int encodedActionParamId = actionMsg.getParams(0).getParamId();
158 assertThat(encodedActionParamId, is(p4InfoActionParamId));
159
160 // Action param value.
161 byte[] encodedActionParam = actionMsg.getParams(0).getValue().toByteArray();
162 assertThat(encodedActionParam, is(portValue.asArray()));
163
164 // TODO: improve, assert other field match types (ternary, LPM)
165 }
166
167// @Test
168// public void testRuntime() throws ExecutionException, InterruptedException {
169//
170// // FIXME: remove me.
171//
172// P4RuntimeControllerImpl controller = new P4RuntimeControllerImpl();
173// GrpcControllerImpl grpcController = new GrpcControllerImpl();
174// controller.grpcController = grpcController;
175// GrpcControllerImpl.ENABLE_MESSAGE_LOG = true;
176// grpcController.activate();
177// DeviceId deviceId = DeviceId.deviceId("dummy:1");
178//
179// ManagedChannelBuilder channelBuilder = NettyChannelBuilder
180// .forAddress("192.168.56.102", 55044)
181// .usePlaintext(true);
182//
183// assert (controller.createClient(deviceId, 1, channelBuilder));
184//
185// P4RuntimeClient client = controller.getClient(deviceId);
186//
187// assert(client.setPipelineConfig(defaultPipeconf, PiPipeconf.ExtensionType.BMV2_JSON).get());
188//
189// assert(client.initStreamChannel().get());
190//
191// assert(client.dumpTable(PiTableId.of(TABLE_0), defaultPipeconf).get().size() == 0);
192//
193// assert(client.writeTableEntries(Lists.newArrayList(piTableEntry), INSERT, defaultPipeconf).get());
194//
195// assert(client.dumpTable(PiTableId.of(TABLE_0), defaultPipeconf).get().size() == 1);
196// }
197}