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