blob: b805aa9a13505cbcf88a456f9802cbad2f3af44f [file] [log] [blame]
Carmelo Cascone8d99b172017-07-18 17:26:31 -04001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Carmelo Cascone8d99b172017-07-18 17:26:31 -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.ctl;
18
19import com.google.common.collect.Lists;
20import com.google.common.testing.EqualsTester;
Yi Tseng82512da2017-08-16 19:46:36 -070021import org.easymock.EasyMock;
Carmelo Cascone8d99b172017-07-18 17:26:31 -040022import org.junit.Test;
23import org.onlab.util.ImmutableByteSequence;
Carmelo Cascone8d99b172017-07-18 17:26:31 -040024import org.onosproject.net.pi.model.DefaultPiPipeconf;
Carmelo Cascone87892e22017-11-13 16:01:29 -080025import org.onosproject.net.pi.model.PiActionId;
26import org.onosproject.net.pi.model.PiActionParamId;
27import org.onosproject.net.pi.model.PiMatchFieldId;
Carmelo Cascone8d99b172017-07-18 17:26:31 -040028import org.onosproject.net.pi.model.PiPipeconf;
29import org.onosproject.net.pi.model.PiPipeconfId;
Yi Tseng82512da2017-08-16 19:46:36 -070030import org.onosproject.net.pi.model.PiPipelineModel;
Carmelo Cascone87892e22017-11-13 16:01:29 -080031import org.onosproject.net.pi.model.PiTableId;
Carmelo Cascone8d99b172017-07-18 17:26:31 -040032import org.onosproject.net.pi.runtime.PiAction;
Carmelo Cascone8d99b172017-07-18 17:26:31 -040033import org.onosproject.net.pi.runtime.PiActionParam;
Carmelo Cascone0e896a02017-07-31 07:22:27 +020034import org.onosproject.net.pi.runtime.PiMatchKey;
Carmelo Cascone8d99b172017-07-18 17:26:31 -040035import org.onosproject.net.pi.runtime.PiTableEntry;
Carmelo Cascone8d99b172017-07-18 17:26:31 -040036import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
37import p4.P4RuntimeOuterClass.Action;
38import p4.P4RuntimeOuterClass.TableEntry;
39
40import java.net.URL;
41import java.util.Collection;
42import java.util.Random;
43
44import static org.hamcrest.MatcherAssert.assertThat;
45import static org.hamcrest.Matchers.hasSize;
46import static org.hamcrest.Matchers.is;
Carmelo Casconeca94bcf2017-10-27 14:16:59 -070047import static org.onlab.util.ImmutableByteSequence.copyFrom;
48import static org.onlab.util.ImmutableByteSequence.fit;
49import static org.onlab.util.ImmutableByteSequence.ofOnes;
Carmelo Cascone8d99b172017-07-18 17:26:31 -040050import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.P4_INFO_TEXT;
51import static org.onosproject.p4runtime.ctl.TableEntryEncoder.decode;
52import static org.onosproject.p4runtime.ctl.TableEntryEncoder.encode;
Andrea Campanellafc1d34c2017-07-18 17:01:41 +020053
Yi Tseng82512da2017-08-16 19:46:36 -070054/**
55 * Test for P4 runtime table entry encoder.
56 */
Carmelo Cascone8d99b172017-07-18 17:26:31 -040057public class TableEntryEncoderTest {
Carmelo Cascone87892e22017-11-13 16:01:29 -080058 private static final String DOT = ".";
Carmelo Cascone8d99b172017-07-18 17:26:31 -040059 private static final String TABLE_0 = "table0";
60 private static final String SET_EGRESS_PORT = "set_egress_port";
61 private static final String PORT = "port";
Carmelo Cascone87892e22017-11-13 16:01:29 -080062 private static final String HDR = "hdr";
Carmelo Cascone8d99b172017-07-18 17:26:31 -040063 private static final String ETHERNET = "ethernet";
64 private static final String DST_ADDR = "dstAddr";
65 private static final String SRC_ADDR = "srcAddr";
66 private static final String STANDARD_METADATA = "standard_metadata";
67 private static final String INGRESS_PORT = "ingress_port";
68 private static final String ETHER_TYPE = "etherType";
69
70 private final Random rand = new Random();
Carmelo Casconeca94bcf2017-10-27 14:16:59 -070071 private final URL p4InfoUrl = this.getClass().getResource("/test.p4info");
Carmelo Cascone8d99b172017-07-18 17:26:31 -040072
73 private final PiPipeconf defaultPipeconf = DefaultPiPipeconf.builder()
74 .withId(new PiPipeconfId("mock"))
Yi Tseng82512da2017-08-16 19:46:36 -070075 .withPipelineModel(EasyMock.niceMock(PiPipelineModel.class))
Carmelo Cascone8d99b172017-07-18 17:26:31 -040076 .addExtension(P4_INFO_TEXT, p4InfoUrl)
Carmelo Cascone8d99b172017-07-18 17:26:31 -040077 .build();
78
79 private final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(defaultPipeconf);
80 private final ImmutableByteSequence ethAddr = fit(copyFrom(rand.nextInt()), 48);
81 private final ImmutableByteSequence portValue = copyFrom((short) rand.nextInt());
Carmelo Cascone87892e22017-11-13 16:01:29 -080082 private final PiMatchFieldId ethDstAddrFieldId = PiMatchFieldId.of(HDR + DOT + ETHERNET + DOT + DST_ADDR);
83 private final PiMatchFieldId ethSrcAddrFieldId = PiMatchFieldId.of(HDR + DOT + ETHERNET + DOT + SRC_ADDR);
84 private final PiMatchFieldId inPortFieldId = PiMatchFieldId.of(STANDARD_METADATA + DOT + INGRESS_PORT);
85 private final PiMatchFieldId ethTypeFieldId = PiMatchFieldId.of(HDR + DOT + ETHERNET + DOT + ETHER_TYPE);
Carmelo Cascone8d99b172017-07-18 17:26:31 -040086 private final PiActionParamId portParamId = PiActionParamId.of(PORT);
87 private final PiActionId outActionId = PiActionId.of(SET_EGRESS_PORT);
88 private final PiTableId tableId = PiTableId.of(TABLE_0);
89
90 private final PiTableEntry piTableEntry = PiTableEntry
91 .builder()
92 .forTable(tableId)
Carmelo Cascone0e896a02017-07-31 07:22:27 +020093 .withMatchKey(PiMatchKey.builder()
94 .addFieldMatch(new PiTernaryFieldMatch(ethDstAddrFieldId, ethAddr, ofOnes(6)))
95 .addFieldMatch(new PiTernaryFieldMatch(ethSrcAddrFieldId, ethAddr, ofOnes(6)))
96 .addFieldMatch(new PiTernaryFieldMatch(inPortFieldId, portValue, ofOnes(2)))
97 .addFieldMatch(new PiTernaryFieldMatch(ethTypeFieldId, portValue, ofOnes(2)))
98 .build())
Carmelo Cascone8d99b172017-07-18 17:26:31 -040099 .withAction(PiAction
Carmelo Cascone0e896a02017-07-31 07:22:27 +0200100 .builder()
101 .withId(outActionId)
102 .withParameter(new PiActionParam(portParamId, portValue))
103 .build())
Carmelo Cascone8d99b172017-07-18 17:26:31 -0400104 .withPriority(1)
105 .withCookie(2)
106 .build();
107
108 public TableEntryEncoderTest() throws ImmutableByteSequence.ByteSequenceTrimException {
109 }
110
111 @Test
112 public void testP4InfoBrowser() throws Exception {
113
114 P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(defaultPipeconf);
115
116 assertThat(browser.tables().hasName(TABLE_0), is(true));
117 assertThat(browser.actions().hasName(SET_EGRESS_PORT), is(true));
118
Carmelo Casconecb0a49c2017-10-03 14:32:23 +0200119 int tableId = browser.tables().getByName(TABLE_0).getPreamble().getId();
120 int actionId = browser.actions().getByName(SET_EGRESS_PORT).getPreamble().getId();
Carmelo Cascone8d99b172017-07-18 17:26:31 -0400121
Carmelo Cascone87892e22017-11-13 16:01:29 -0800122 assertThat(browser.matchFields(tableId).hasName(STANDARD_METADATA + DOT + INGRESS_PORT), is(true));
Carmelo Cascone8d99b172017-07-18 17:26:31 -0400123 assertThat(browser.actionParams(actionId).hasName(PORT), is(true));
124
125 // TODO: improve, assert browsing other entities (counters, meters, etc.)
126 }
127
128 @Test
129 public void testTableEntryEncoder()
130 throws P4InfoBrowser.NotFoundException, ImmutableByteSequence.ByteSequenceTrimException {
131
132 Collection<TableEntry> result = encode(Lists.newArrayList(piTableEntry), defaultPipeconf);
133 assertThat(result, hasSize(1));
134
135 TableEntry tableEntryMsg = result.iterator().next();
136
137 Collection<PiTableEntry> decodedResults = decode(Lists.newArrayList(tableEntryMsg), defaultPipeconf);
138 PiTableEntry decodedPiTableEntry = decodedResults.iterator().next();
139
140 // Test equality for decoded entry.
141 new EqualsTester()
142 .addEqualityGroup(piTableEntry, decodedPiTableEntry)
143 .testEquals();
144
145 // Table ID.
Carmelo Casconecb0a49c2017-10-03 14:32:23 +0200146 int p4InfoTableId = browser.tables().getByName(tableId.id()).getPreamble().getId();
Carmelo Cascone8d99b172017-07-18 17:26:31 -0400147 int encodedTableId = tableEntryMsg.getTableId();
148 assertThat(encodedTableId, is(p4InfoTableId));
149
150 // Ternary match.
151 byte[] encodedTernaryMatchValue = tableEntryMsg.getMatch(0).getTernary().getValue().toByteArray();
152 assertThat(encodedTernaryMatchValue, is(ethAddr.asArray()));
153
154 Action actionMsg = tableEntryMsg.getAction().getAction();
155
156 // Action ID.
Carmelo Cascone87892e22017-11-13 16:01:29 -0800157 int p4InfoActionId = browser.actions().getByName(outActionId.toString()).getPreamble().getId();
Carmelo Cascone8d99b172017-07-18 17:26:31 -0400158 int encodedActionId = actionMsg.getActionId();
159 assertThat(encodedActionId, is(p4InfoActionId));
160
161 // Action param ID.
Carmelo Cascone87892e22017-11-13 16:01:29 -0800162 int p4InfoActionParamId = browser.actionParams(p4InfoActionId).getByName(portParamId.toString()).getId();
Carmelo Cascone8d99b172017-07-18 17:26:31 -0400163 int encodedActionParamId = actionMsg.getParams(0).getParamId();
164 assertThat(encodedActionParamId, is(p4InfoActionParamId));
165
166 // Action param value.
167 byte[] encodedActionParam = actionMsg.getParams(0).getValue().toByteArray();
168 assertThat(encodedActionParam, is(portValue.asArray()));
169
170 // TODO: improve, assert other field match types (ternary, LPM)
171 }
Carmelo Cascone8d99b172017-07-18 17:26:31 -0400172}