blob: 513b4fa3ba3aef52fe5589a580f1aa6eceaee290 [file] [log] [blame]
Carmelo Cascone4c289b72019-01-22 15:30:45 -08001/*
2 * Copyright 2019-present Open Networking Foundation
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.codec;
18
19import org.onosproject.net.pi.model.PiPipeconf;
20import org.onosproject.net.pi.model.PiTableId;
21import org.onosproject.net.pi.runtime.PiAction;
22import org.onosproject.net.pi.runtime.PiActionProfileGroupId;
23import org.onosproject.net.pi.runtime.PiActionProfileMemberId;
24import org.onosproject.net.pi.runtime.PiCounterCellData;
25import org.onosproject.net.pi.runtime.PiMatchKey;
26import org.onosproject.net.pi.runtime.PiTableAction;
27import org.onosproject.net.pi.runtime.PiTableEntry;
28import org.onosproject.net.pi.runtime.PiTableEntryHandle;
29import org.onosproject.p4runtime.ctl.utils.P4InfoBrowser;
30import p4.config.v1.P4InfoOuterClass;
31import p4.v1.P4RuntimeOuterClass;
32
33import java.util.OptionalInt;
34
35import static com.google.common.base.Preconditions.checkNotNull;
36import static java.lang.String.format;
37import static org.onosproject.p4runtime.ctl.codec.Codecs.CODECS;
38
39/**
40 * Codec for P4Runtime TableEntry.
41 */
42public final class TableEntryCodec
43 extends AbstractEntityCodec<PiTableEntry, PiTableEntryHandle,
44 P4RuntimeOuterClass.TableEntry, Object> {
45
46 @Override
47 protected P4RuntimeOuterClass.TableEntry encode(
48 PiTableEntry piTableEntry, Object ignored, PiPipeconf pipeconf,
49 P4InfoBrowser browser)
50 throws CodecException, P4InfoBrowser.NotFoundException {
51 final P4RuntimeOuterClass.TableEntry.Builder tableEntryMsgBuilder =
52 keyMsgBuilder(piTableEntry.table(), piTableEntry.matchKey(),
53 piTableEntry.priority(), pipeconf, browser);
54 // Controller metadata (cookie)
55 tableEntryMsgBuilder.setControllerMetadata(piTableEntry.cookie());
56 // Timeout.
57 if (piTableEntry.timeout().isPresent()) {
58 // FIXME: timeout is supported in P4Runtime v1.0
59 log.warn("Found PI table entry with timeout set, " +
60 "not supported in P4Runtime: {}", piTableEntry);
61 }
62 // Table action.
63 if (piTableEntry.action() != null) {
64 tableEntryMsgBuilder.setAction(
65 encodePiTableAction(piTableEntry.action(), pipeconf));
66 }
67 // Counter.
68 if (piTableEntry.counter() != null) {
69 tableEntryMsgBuilder.setCounterData(encodeCounter(piTableEntry.counter()));
70 }
71 return tableEntryMsgBuilder.build();
72 }
73
74 @Override
75 protected P4RuntimeOuterClass.TableEntry encodeKey(
76 PiTableEntryHandle handle, Object metadata, PiPipeconf pipeconf,
77 P4InfoBrowser browser) throws CodecException, P4InfoBrowser.NotFoundException {
78 return keyMsgBuilder(handle.tableId(), handle.matchKey(),
79 handle.priority(), pipeconf, browser).build();
80 }
81
82 @Override
83 protected P4RuntimeOuterClass.TableEntry encodeKey(
84 PiTableEntry piEntity, Object metadata, PiPipeconf pipeconf,
85 P4InfoBrowser browser) throws CodecException, P4InfoBrowser.NotFoundException {
86 return keyMsgBuilder(piEntity.table(), piEntity.matchKey(),
87 piEntity.priority(), pipeconf, browser).build();
88 }
89
90 @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
91 private P4RuntimeOuterClass.TableEntry.Builder keyMsgBuilder(
92 PiTableId tableId, PiMatchKey matchKey, OptionalInt priority,
93 PiPipeconf pipeconf, P4InfoBrowser browser)
94 throws P4InfoBrowser.NotFoundException, CodecException {
95 final P4RuntimeOuterClass.TableEntry.Builder tableEntryMsgBuilder =
96 P4RuntimeOuterClass.TableEntry.newBuilder();
97 final P4InfoOuterClass.Preamble tablePreamble = browser.tables()
98 .getByName(tableId.id()).getPreamble();
99 // Table id.
100 tableEntryMsgBuilder.setTableId(tablePreamble.getId());
101 // Field matches.
102 if (matchKey.equals(PiMatchKey.EMPTY)) {
103 tableEntryMsgBuilder.setIsDefaultAction(true);
104 } else {
105 tableEntryMsgBuilder.addAllMatch(
106 CODECS.fieldMatch().encodeAll(
107 matchKey.fieldMatches(),
108 tablePreamble, pipeconf));
109 }
110 // Priority.
111 priority.ifPresent(tableEntryMsgBuilder::setPriority);
112 return tableEntryMsgBuilder;
113 }
114
115 @Override
116 protected PiTableEntry decode(
117 P4RuntimeOuterClass.TableEntry message, Object ignored,
118 PiPipeconf pipeconf, P4InfoBrowser browser)
119 throws CodecException, P4InfoBrowser.NotFoundException {
120 PiTableEntry.Builder piTableEntryBuilder = PiTableEntry.builder();
121
122 P4InfoOuterClass.Preamble tablePreamble = browser.tables()
123 .getById(message.getTableId()).getPreamble();
124
125 // Table id.
126 piTableEntryBuilder.forTable(PiTableId.of(tablePreamble.getName()));
127
128 // Priority.
129 if (message.getPriority() > 0) {
130 piTableEntryBuilder.withPriority(message.getPriority());
131 }
132
133 // Controller metadata (cookie)
134 piTableEntryBuilder.withCookie(message.getControllerMetadata());
135
136 // Table action.
137 if (message.hasAction()) {
138 piTableEntryBuilder.withAction(decodeTableActionMsg(
139 message.getAction(), pipeconf));
140 }
141
142 // Timeout.
143 // FIXME: how to decode table entry messages with timeout, given that
144 // the timeout value is lost after encoding?
145
146 // Match key for field matches.
147 piTableEntryBuilder.withMatchKey(
148 PiMatchKey.builder()
149 .addFieldMatches(CODECS.fieldMatch().decodeAll(
150 message.getMatchList(),
151 tablePreamble, pipeconf))
152 .build());
153
154 // Counter.
Carmelo Casconec32976e2019-04-08 14:50:52 -0700155 if (message.hasCounterData()) {
156 piTableEntryBuilder.withCounterCellData(decodeCounter(message.getCounterData()));
157 }
Carmelo Cascone4c289b72019-01-22 15:30:45 -0800158
159 return piTableEntryBuilder.build();
160 }
161
162 private P4RuntimeOuterClass.TableAction encodePiTableAction(
163 PiTableAction piTableAction, PiPipeconf pipeconf)
164 throws CodecException {
165 checkNotNull(piTableAction, "Cannot encode null PiTableAction");
166 final P4RuntimeOuterClass.TableAction.Builder tableActionMsgBuilder =
167 P4RuntimeOuterClass.TableAction.newBuilder();
168 switch (piTableAction.type()) {
169 case ACTION:
170 P4RuntimeOuterClass.Action theAction = CODECS.action()
171 .encode((PiAction) piTableAction, null, pipeconf);
172 tableActionMsgBuilder.setAction(theAction);
173 break;
174 case ACTION_PROFILE_GROUP_ID:
175 tableActionMsgBuilder.setActionProfileGroupId(
176 ((PiActionProfileGroupId) piTableAction).id());
177 break;
178 case ACTION_PROFILE_MEMBER_ID:
179 tableActionMsgBuilder.setActionProfileMemberId(
180 ((PiActionProfileMemberId) piTableAction).id());
181 break;
182 default:
183 throw new CodecException(
184 format("Building of table action type %s not implemented",
185 piTableAction.type()));
186 }
187 return tableActionMsgBuilder.build();
188 }
189
190 private PiTableAction decodeTableActionMsg(
191 P4RuntimeOuterClass.TableAction tableActionMsg, PiPipeconf pipeconf)
192 throws CodecException {
193 P4RuntimeOuterClass.TableAction.TypeCase typeCase = tableActionMsg.getTypeCase();
194 switch (typeCase) {
195 case ACTION:
196 P4RuntimeOuterClass.Action actionMsg = tableActionMsg.getAction();
197 return CODECS.action().decode(
198 actionMsg, null, pipeconf);
199 case ACTION_PROFILE_GROUP_ID:
200 return PiActionProfileGroupId.of(
201 tableActionMsg.getActionProfileGroupId());
202 case ACTION_PROFILE_MEMBER_ID:
203 return PiActionProfileMemberId.of(
204 tableActionMsg.getActionProfileMemberId());
205 default:
206 throw new CodecException(
207 format("Decoding of table action type %s not implemented",
208 typeCase.name()));
209 }
210 }
211
212 private P4RuntimeOuterClass.CounterData encodeCounter(
213 PiCounterCellData piCounterCellData) {
214 return P4RuntimeOuterClass.CounterData.newBuilder()
215 .setPacketCount(piCounterCellData.packets())
216 .setByteCount(piCounterCellData.bytes()).build();
217 }
218
219 private PiCounterCellData decodeCounter(
220 P4RuntimeOuterClass.CounterData counterData) {
221 return new PiCounterCellData(
222 counterData.getPacketCount(), counterData.getByteCount());
223 }
224}