blob: cbe1d6e1d198e281e78b7a7326d45970cb0907f8 [file] [log] [blame]
Carmelo Cascone87892e22017-11-13 16:01:29 -08001/*
2 * Copyright 2017-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.model;
18
19import com.google.common.collect.ImmutableList;
20import com.google.common.collect.ImmutableMap;
21import com.google.common.collect.ImmutableSet;
22import com.google.common.collect.Maps;
pierventre69329172021-01-10 17:29:03 -080023import com.google.common.hash.Hashing;
24import com.google.common.hash.HashingInputStream;
Carmelo Cascone87892e22017-11-13 16:01:29 -080025import com.google.protobuf.ExtensionRegistry;
26import com.google.protobuf.TextFormat;
27import org.onosproject.net.pi.model.PiActionId;
28import org.onosproject.net.pi.model.PiActionModel;
29import org.onosproject.net.pi.model.PiActionParamId;
30import org.onosproject.net.pi.model.PiActionParamModel;
31import org.onosproject.net.pi.model.PiActionProfileId;
32import org.onosproject.net.pi.model.PiActionProfileModel;
Carmelo Cascone87892e22017-11-13 16:01:29 -080033import org.onosproject.net.pi.model.PiCounterId;
34import org.onosproject.net.pi.model.PiCounterModel;
35import org.onosproject.net.pi.model.PiCounterType;
36import org.onosproject.net.pi.model.PiMatchFieldId;
37import org.onosproject.net.pi.model.PiMatchFieldModel;
38import org.onosproject.net.pi.model.PiMatchType;
39import org.onosproject.net.pi.model.PiMeterId;
40import org.onosproject.net.pi.model.PiMeterModel;
41import org.onosproject.net.pi.model.PiMeterType;
Carmelo Casconea3635ab2019-03-19 12:55:34 -070042import org.onosproject.net.pi.model.PiPacketMetadataId;
43import org.onosproject.net.pi.model.PiPacketMetadataModel;
Carmelo Cascone87892e22017-11-13 16:01:29 -080044import org.onosproject.net.pi.model.PiPacketOperationModel;
45import org.onosproject.net.pi.model.PiPacketOperationType;
46import org.onosproject.net.pi.model.PiPipelineModel;
FrankWang2674e452018-05-24 17:13:35 +080047import org.onosproject.net.pi.model.PiRegisterId;
48import org.onosproject.net.pi.model.PiRegisterModel;
Carmelo Cascone87892e22017-11-13 16:01:29 -080049import org.onosproject.net.pi.model.PiTableId;
50import org.onosproject.net.pi.model.PiTableModel;
51import org.onosproject.net.pi.model.PiTableType;
Carmelo Casconea3635ab2019-03-19 12:55:34 -070052import org.slf4j.Logger;
Carmelo Cascone6af4e172018-06-15 16:01:30 +020053import p4.config.v1.P4InfoOuterClass;
54import p4.config.v1.P4InfoOuterClass.Action;
55import p4.config.v1.P4InfoOuterClass.ActionProfile;
56import p4.config.v1.P4InfoOuterClass.ActionRef;
57import p4.config.v1.P4InfoOuterClass.ControllerPacketMetadata;
58import p4.config.v1.P4InfoOuterClass.Counter;
59import p4.config.v1.P4InfoOuterClass.CounterSpec;
60import p4.config.v1.P4InfoOuterClass.DirectCounter;
61import p4.config.v1.P4InfoOuterClass.DirectMeter;
62import p4.config.v1.P4InfoOuterClass.MatchField;
63import p4.config.v1.P4InfoOuterClass.Meter;
64import p4.config.v1.P4InfoOuterClass.MeterSpec;
65import p4.config.v1.P4InfoOuterClass.P4Info;
66import p4.config.v1.P4InfoOuterClass.Table;
Daniele Moro5c82b0f2020-12-07 20:56:30 +010067import p4.config.v1.P4Types;
Carmelo Cascone87892e22017-11-13 16:01:29 -080068
69import java.io.IOException;
70import java.io.InputStream;
71import java.io.InputStreamReader;
72import java.net.URL;
73import java.util.Map;
74import java.util.Objects;
75import java.util.stream.Collectors;
76
77import static java.lang.String.format;
Daniele Morod900fe42021-02-11 16:12:57 +010078import static org.onosproject.p4runtime.model.P4InfoAnnotationUtils.MAX_GROUP_SIZE_ANNOTATION;
79import static org.onosproject.p4runtime.model.P4InfoAnnotationUtils.ONE_SHOT_ONLY_ANNOTATION;
80import static org.onosproject.p4runtime.model.P4InfoAnnotationUtils.getAnnotationValue;
81import static org.onosproject.p4runtime.model.P4InfoAnnotationUtils.isAnnotationPresent;
Carmelo Casconea3635ab2019-03-19 12:55:34 -070082import static org.slf4j.LoggerFactory.getLogger;
Carmelo Cascone87892e22017-11-13 16:01:29 -080083
84/**
85 * Parser of P4Info to PI pipeline model instances.
86 */
87public final class P4InfoParser {
88
Carmelo Casconea3635ab2019-03-19 12:55:34 -070089 private static final Logger log = getLogger(P4InfoParser.class);
90
Carmelo Cascone87892e22017-11-13 16:01:29 -080091 private static final String PACKET_IN = "packet_in";
92 private static final String PACKET_OUT = "packet_out";
93
Daniele Morod900fe42021-02-11 16:12:57 +010094
Carmelo Cascone87892e22017-11-13 16:01:29 -080095 private static final Map<CounterSpec.Unit, PiCounterModel.Unit> COUNTER_UNIT_MAP =
96 new ImmutableMap.Builder<CounterSpec.Unit, PiCounterModel.Unit>()
97 .put(CounterSpec.Unit.BYTES, PiCounterModel.Unit.BYTES)
98 .put(CounterSpec.Unit.PACKETS, PiCounterModel.Unit.PACKETS)
99 .put(CounterSpec.Unit.BOTH, PiCounterModel.Unit.PACKETS_AND_BYTES)
100 // Don't map UNSPECIFIED as we don't support it at the moment.
101 .build();
102
103 private static final Map<MeterSpec.Unit, PiMeterModel.Unit> METER_UNIT_MAP =
104 new ImmutableMap.Builder<MeterSpec.Unit, PiMeterModel.Unit>()
105 .put(MeterSpec.Unit.BYTES, PiMeterModel.Unit.BYTES)
106 .put(MeterSpec.Unit.PACKETS, PiMeterModel.Unit.PACKETS)
107 // Don't map UNSPECIFIED as we don't support it at the moment.
108 .build();
109
110 private static final Map<String, PiPacketOperationType> PACKET_OPERATION_TYPE_MAP =
111 new ImmutableMap.Builder<String, PiPacketOperationType>()
112 .put(PACKET_IN, PiPacketOperationType.PACKET_IN)
113 .put(PACKET_OUT, PiPacketOperationType.PACKET_OUT)
114 .build();
115
116 private static final Map<MatchField.MatchType, PiMatchType> MATCH_TYPE_MAP =
117 new ImmutableMap.Builder<MatchField.MatchType, PiMatchType>()
Carmelo Cascone87892e22017-11-13 16:01:29 -0800118 .put(MatchField.MatchType.EXACT, PiMatchType.EXACT)
119 .put(MatchField.MatchType.LPM, PiMatchType.LPM)
120 .put(MatchField.MatchType.TERNARY, PiMatchType.TERNARY)
121 .put(MatchField.MatchType.RANGE, PiMatchType.RANGE)
Daniele Moroc6f2f7f2020-12-18 10:55:57 +0100122 .put(MatchField.MatchType.OPTIONAL, PiMatchType.OPTIONAL)
Carmelo Cascone87892e22017-11-13 16:01:29 -0800123 // Don't map UNSPECIFIED as we don't support it at the moment.
124 .build();
125 public static final int NO_SIZE = -1;
126
127 private P4InfoParser() {
128 // Utility class, hides constructor.
129 }
130
131 /**
132 * Parse the given URL pointing to a P4Info file (in text format) to a PI pipeline model.
133 *
134 * @param p4InfoUrl URL to P4Info in text form
135 * @return PI pipeline model
136 * @throws P4InfoParserException if the P4Info file cannot be parsed (see message)
137 */
138 public static PiPipelineModel parse(URL p4InfoUrl) throws P4InfoParserException {
139
140 final P4Info p4info;
141 try {
142 p4info = getP4InfoMessage(p4InfoUrl);
143 } catch (IOException e) {
144 throw new P4InfoParserException("Unable to parse protobuf " + p4InfoUrl.toString(), e);
145 }
146
pierventre69329172021-01-10 17:29:03 -0800147 // Generate fingerprint of the pipeline by hashing p4info file
148 final int fingerprint;
149 try {
150 HashingInputStream hin = new HashingInputStream(Hashing.crc32(), p4InfoUrl.openStream());
151 //noinspection StatementWithEmptyBody
152 while (hin.read() != -1) {
153 // Do nothing. Reading all input stream to update hash.
154 }
155 fingerprint = hin.hash().asInt();
156 } catch (IOException e) {
157 throw new P4InfoParserException("Unable to generate fingerprint " + p4InfoUrl.toString(), e);
158 }
159
Carmelo Cascone87892e22017-11-13 16:01:29 -0800160 // Start by parsing and mapping instances to to their integer P4Info IDs.
161 // Convenient to build the table model at the end.
162
163 // Counters.
164 final Map<Integer, PiCounterModel> counterMap = Maps.newHashMap();
165 counterMap.putAll(parseCounters(p4info));
166 counterMap.putAll(parseDirectCounters(p4info));
167
168 // Meters.
169 final Map<Integer, PiMeterModel> meterMap = Maps.newHashMap();
170 meterMap.putAll(parseMeters(p4info));
171 meterMap.putAll(parseDirectMeters(p4info));
172
FrankWang2674e452018-05-24 17:13:35 +0800173 // Registers.
174 final Map<Integer, PiRegisterModel> registerMap = Maps.newHashMap();
175 registerMap.putAll(parseRegisters(p4info));
176
Carmelo Cascone87892e22017-11-13 16:01:29 -0800177 // Action profiles.
178 final Map<Integer, PiActionProfileModel> actProfileMap = parseActionProfiles(p4info);
179
180 // Actions.
181 final Map<Integer, PiActionModel> actionMap = parseActions(p4info);
182
183 // Controller packet metadatas.
184 final Map<PiPacketOperationType, PiPacketOperationModel> pktOpMap = parseCtrlPktMetadatas(p4info);
185
186 // Finally, parse tables.
187 final ImmutableMap.Builder<PiTableId, PiTableModel> tableImmMapBuilder =
188 ImmutableMap.builder();
189 for (Table tableMsg : p4info.getTablesList()) {
190 final PiTableId tableId = PiTableId.of(tableMsg.getPreamble().getName());
191 // Parse match fields.
192 final ImmutableMap.Builder<PiMatchFieldId, PiMatchFieldModel> tableFieldMapBuilder =
193 ImmutableMap.builder();
194 for (MatchField fieldMsg : tableMsg.getMatchFieldsList()) {
195 final PiMatchFieldId fieldId = PiMatchFieldId.of(fieldMsg.getName());
196 tableFieldMapBuilder.put(
197 fieldId,
198 new P4MatchFieldModel(fieldId,
Daniele Moro5c82b0f2020-12-07 20:56:30 +0100199 isFieldString(p4info, fieldMsg.getTypeName().getName()) ?
200 P4MatchFieldModel.BIT_WIDTH_UNDEFINED :
201 fieldMsg.getBitwidth(),
Carmelo Cascone87892e22017-11-13 16:01:29 -0800202 mapMatchFieldType(fieldMsg.getMatchType())));
203
204 }
205 // Retrieve action models by inter IDs.
206 final ImmutableMap.Builder<PiActionId, PiActionModel> tableActionMapBuilder =
207 ImmutableMap.builder();
208 tableMsg.getActionRefsList().stream()
209 .map(ActionRef::getId)
210 .map(actionMap::get)
211 .forEach(actionModel -> tableActionMapBuilder.put(actionModel.id(), actionModel));
212 // Retrieve direct meters by integer IDs.
213 final ImmutableMap.Builder<PiMeterId, PiMeterModel> tableMeterMapBuilder =
214 ImmutableMap.builder();
215 tableMsg.getDirectResourceIdsList()
216 .stream()
217 .map(meterMap::get)
218 // Direct resource ID might be that of a counter.
219 // Filter out missed mapping.
220 .filter(Objects::nonNull)
221 .forEach(meterModel -> tableMeterMapBuilder.put(meterModel.id(), meterModel));
222 // Retrieve direct counters by integer IDs.
223 final ImmutableMap.Builder<PiCounterId, PiCounterModel> tableCounterMapBuilder =
224 ImmutableMap.builder();
225 tableMsg.getDirectResourceIdsList()
226 .stream()
227 .map(counterMap::get)
228 // As before, resource ID might be that of a meter.
229 // Filter out missed mapping.
230 .filter(Objects::nonNull)
231 .forEach(counterModel -> tableCounterMapBuilder.put(counterModel.id(), counterModel));
Daniele Morod900fe42021-02-11 16:12:57 +0100232 // Check if table supports one-shot only
233 boolean oneShotOnly = isAnnotationPresent(ONE_SHOT_ONLY_ANNOTATION, tableMsg.getPreamble());
Carmelo Cascone87892e22017-11-13 16:01:29 -0800234 tableImmMapBuilder.put(
235 tableId,
236 new P4TableModel(
237 PiTableId.of(tableMsg.getPreamble().getName()),
238 tableMsg.getImplementationId() == 0 ? PiTableType.DIRECT : PiTableType.INDIRECT,
239 actProfileMap.get(tableMsg.getImplementationId()),
240 tableMsg.getSize(),
241 tableCounterMapBuilder.build(),
242 tableMeterMapBuilder.build(),
Carmelo Cascone6af4e172018-06-15 16:01:30 +0200243 !tableMsg.getIdleTimeoutBehavior()
244 .equals(Table.IdleTimeoutBehavior.NO_TIMEOUT),
Carmelo Cascone87892e22017-11-13 16:01:29 -0800245 tableFieldMapBuilder.build(),
246 tableActionMapBuilder.build(),
247 actionMap.get(tableMsg.getConstDefaultActionId()),
Daniele Morod900fe42021-02-11 16:12:57 +0100248 tableMsg.getIsConstTable(), oneShotOnly));
Carmelo Cascone87892e22017-11-13 16:01:29 -0800249 }
250
251 // Get a map with proper PI IDs for some of those maps we created at the beginning.
252 ImmutableMap<PiCounterId, PiCounterModel> counterImmMap = ImmutableMap.copyOf(
253 counterMap.values().stream()
254 .collect(Collectors.toMap(PiCounterModel::id, c -> c)));
255 ImmutableMap<PiMeterId, PiMeterModel> meterImmMap = ImmutableMap.copyOf(
256 meterMap.values().stream()
257 .collect(Collectors.toMap(PiMeterModel::id, m -> m)));
FrankWang2674e452018-05-24 17:13:35 +0800258 ImmutableMap<PiRegisterId, PiRegisterModel> registerImmMap = ImmutableMap.copyOf(
259 registerMap.values().stream()
260 .collect(Collectors.toMap(PiRegisterModel::id, r -> r)));
Carmelo Cascone87892e22017-11-13 16:01:29 -0800261 ImmutableMap<PiActionProfileId, PiActionProfileModel> actProfileImmMap = ImmutableMap.copyOf(
262 actProfileMap.values().stream()
263 .collect(Collectors.toMap(PiActionProfileModel::id, a -> a)));
264
265 return new P4PipelineModel(
266 tableImmMapBuilder.build(),
267 counterImmMap,
268 meterImmMap,
FrankWang2674e452018-05-24 17:13:35 +0800269 registerImmMap,
Carmelo Cascone87892e22017-11-13 16:01:29 -0800270 actProfileImmMap,
pierventre69329172021-01-10 17:29:03 -0800271 ImmutableMap.copyOf(pktOpMap),
272 fingerprint);
Carmelo Cascone87892e22017-11-13 16:01:29 -0800273 }
274
275
276 private static Map<Integer, PiCounterModel> parseCounters(P4Info p4info)
277 throws P4InfoParserException {
278 final Map<Integer, PiCounterModel> counterMap = Maps.newHashMap();
279 for (Counter counterMsg : p4info.getCountersList()) {
280 counterMap.put(
281 counterMsg.getPreamble().getId(),
282 new P4CounterModel(
283 PiCounterId.of(counterMsg.getPreamble().getName()),
284 PiCounterType.INDIRECT,
285 mapCounterSpecUnit(counterMsg.getSpec()),
286 null,
287 counterMsg.getSize()));
288 }
289 return counterMap;
290 }
291
292 private static Map<Integer, PiCounterModel> parseDirectCounters(P4Info p4info)
293 throws P4InfoParserException {
294 final Map<Integer, PiCounterModel> counterMap = Maps.newHashMap();
295 for (DirectCounter dirCounterMsg : p4info.getDirectCountersList()) {
296 counterMap.put(
297 dirCounterMsg.getPreamble().getId(),
298 new P4CounterModel(
299 PiCounterId.of(dirCounterMsg.getPreamble().getName()),
300 PiCounterType.DIRECT,
301 mapCounterSpecUnit(dirCounterMsg.getSpec()),
302 PiTableId.of(getTableName(dirCounterMsg.getDirectTableId(), p4info)),
303 NO_SIZE));
304 }
305 return counterMap;
306 }
307
308 private static Map<Integer, PiMeterModel> parseMeters(P4Info p4info)
309 throws P4InfoParserException {
310 final Map<Integer, PiMeterModel> meterMap = Maps.newHashMap();
311 for (Meter meterMsg : p4info.getMetersList()) {
312 meterMap.put(
313 meterMsg.getPreamble().getId(),
314 new P4MeterModel(
315 PiMeterId.of(meterMsg.getPreamble().getName()),
316 PiMeterType.INDIRECT,
317 mapMeterSpecUnit(meterMsg.getSpec()),
318 null,
319 meterMsg.getSize()));
320 }
321 return meterMap;
322 }
323
324 private static Map<Integer, PiMeterModel> parseDirectMeters(P4Info p4info)
325 throws P4InfoParserException {
326 final Map<Integer, PiMeterModel> meterMap = Maps.newHashMap();
327 for (DirectMeter dirMeterMsg : p4info.getDirectMetersList()) {
328 meterMap.put(
329 dirMeterMsg.getPreamble().getId(),
330 new P4MeterModel(
331 PiMeterId.of(dirMeterMsg.getPreamble().getName()),
332 PiMeterType.DIRECT,
333 mapMeterSpecUnit(dirMeterMsg.getSpec()),
334 PiTableId.of(getTableName(dirMeterMsg.getDirectTableId(), p4info)),
335 NO_SIZE));
336 }
337 return meterMap;
338 }
339
Carmelo Cascone6af4e172018-06-15 16:01:30 +0200340 private static Map<Integer, PiRegisterModel> parseRegisters(P4Info p4info) {
FrankWang2674e452018-05-24 17:13:35 +0800341 final Map<Integer, PiRegisterModel> registerMap = Maps.newHashMap();
342 for (P4InfoOuterClass.Register registerMsg : p4info.getRegistersList()) {
343 registerMap.put(registerMsg.getPreamble().getId(),
344 new P4RegisterModel(PiRegisterId.of(registerMsg.getPreamble().getName()),
345 registerMsg.getSize()));
346 }
347 return registerMap;
348 }
349
Carmelo Cascone87892e22017-11-13 16:01:29 -0800350 private static Map<Integer, PiActionProfileModel> parseActionProfiles(P4Info p4info)
351 throws P4InfoParserException {
352 final Map<Integer, PiActionProfileModel> actProfileMap = Maps.newHashMap();
353 for (ActionProfile actProfileMsg : p4info.getActionProfilesList()) {
354 final ImmutableSet.Builder<PiTableId> tableIdSetBuilder = ImmutableSet.builder();
355 for (int tableId : actProfileMsg.getTableIdsList()) {
356 tableIdSetBuilder.add(PiTableId.of(getTableName(tableId, p4info)));
357 }
Carmelo Casconea3635ab2019-03-19 12:55:34 -0700358 // TODO: we should copy all annotations to model classes for later
359 // use in the PI framework.
360 // This is a temporary workaround to the inability of p4c to
361 // correctly interpret P4Runtime-defined max_group_size annotation:
362 // https://s3-us-west-2.amazonaws.com/p4runtime/docs/master/
363 // P4Runtime-Spec.html#sec-p4info-action-profile
Daniele Morod900fe42021-02-11 16:12:57 +0100364 final String maxSizeAnnString = getAnnotationValue(
365 MAX_GROUP_SIZE_ANNOTATION, actProfileMsg.getPreamble());
Carmelo Casconea3635ab2019-03-19 12:55:34 -0700366 final int maxSizeAnn = maxSizeAnnString != null
367 ? Integer.valueOf(maxSizeAnnString) : 0;
368 final int maxGroupSize;
369 if (actProfileMsg.getMaxGroupSize() == 0 && maxSizeAnn != 0) {
370 log.warn("Found valid 'max_group_size' annotation for " +
371 "ActionProfile {}, using that...",
372 actProfileMsg.getPreamble().getName());
373 maxGroupSize = maxSizeAnn;
374 } else {
375 maxGroupSize = actProfileMsg.getMaxGroupSize();
376 }
377
Carmelo Cascone87892e22017-11-13 16:01:29 -0800378 actProfileMap.put(
379 actProfileMsg.getPreamble().getId(),
380 new P4ActionProfileModel(
381 PiActionProfileId.of(actProfileMsg.getPreamble().getName()),
382 tableIdSetBuilder.build(),
383 actProfileMsg.getWithSelector(),
Carmelo Cascone99c59db2019-01-17 15:39:35 -0800384 actProfileMsg.getSize(),
Carmelo Casconea3635ab2019-03-19 12:55:34 -0700385 maxGroupSize));
Carmelo Cascone87892e22017-11-13 16:01:29 -0800386 }
387 return actProfileMap;
388 }
389
390 private static Map<Integer, PiActionModel> parseActions(P4Info p4info) {
391 final Map<Integer, PiActionModel> actionMap = Maps.newHashMap();
392 for (Action actionMsg : p4info.getActionsList()) {
393 final ImmutableMap.Builder<PiActionParamId, PiActionParamModel> paramMapBuilder =
394 ImmutableMap.builder();
395 actionMsg.getParamsList().forEach(paramMsg -> {
396 final PiActionParamId paramId = PiActionParamId.of(paramMsg.getName());
397 paramMapBuilder.put(paramId,
Daniele Moro5c82b0f2020-12-07 20:56:30 +0100398 new P4ActionParamModel(
399 PiActionParamId.of(paramMsg.getName()),
400 isFieldString(p4info, paramMsg.getTypeName().getName()) ?
401 P4ActionParamModel.BIT_WIDTH_UNDEFINED :
402 paramMsg.getBitwidth()));
Carmelo Cascone87892e22017-11-13 16:01:29 -0800403 });
404 actionMap.put(
405 actionMsg.getPreamble().getId(),
406 new P4ActionModel(
407 PiActionId.of(actionMsg.getPreamble().getName()),
408 paramMapBuilder.build()));
409
410 }
411 return actionMap;
412 }
413
414 private static Map<PiPacketOperationType, PiPacketOperationModel> parseCtrlPktMetadatas(P4Info p4info)
415 throws P4InfoParserException {
416 final Map<PiPacketOperationType, PiPacketOperationModel> packetOpMap = Maps.newHashMap();
417 for (ControllerPacketMetadata ctrlPktMetaMsg : p4info.getControllerPacketMetadataList()) {
Carmelo Cascone4c289b72019-01-22 15:30:45 -0800418 final ImmutableList.Builder<PiPacketMetadataModel> metadataListBuilder =
Carmelo Cascone87892e22017-11-13 16:01:29 -0800419 ImmutableList.builder();
420 ctrlPktMetaMsg.getMetadataList().forEach(metadataMsg -> metadataListBuilder.add(
Carmelo Cascone4c289b72019-01-22 15:30:45 -0800421 new P4PacketMetadataModel(PiPacketMetadataId.of(metadataMsg.getName()),
Daniele Moro23759172021-02-11 17:30:13 +0100422 isFieldString(p4info, metadataMsg.getTypeName().getName()) ?
423 P4PacketMetadataModel.BIT_WIDTH_UNDEFINED :
424 metadataMsg.getBitwidth())));
Carmelo Cascone87892e22017-11-13 16:01:29 -0800425 packetOpMap.put(
426 mapPacketOpType(ctrlPktMetaMsg.getPreamble().getName()),
427 new P4PacketOperationModel(mapPacketOpType(ctrlPktMetaMsg.getPreamble().getName()),
428 metadataListBuilder.build()));
429
430 }
431 return packetOpMap;
432 }
433
434 private static P4Info getP4InfoMessage(URL p4InfoUrl) throws IOException {
435 InputStream p4InfoStream = p4InfoUrl.openStream();
436 P4Info.Builder p4InfoBuilder = P4Info.newBuilder();
437 TextFormat.getParser().merge(new InputStreamReader(p4InfoStream),
438 ExtensionRegistry.getEmptyRegistry(),
439 p4InfoBuilder);
440 return p4InfoBuilder.build();
441 }
442
443 private static String getTableName(int id, P4Info p4info)
444 throws P4InfoParserException {
445 return p4info.getTablesList().stream()
446 .filter(t -> t.getPreamble().getId() == id)
447 .findFirst()
448 .orElseThrow(() -> new P4InfoParserException(format(
449 "Not such table with ID %d", id)))
450 .getPreamble()
451 .getName();
452 }
453
454 private static PiCounterModel.Unit mapCounterSpecUnit(CounterSpec spec)
455 throws P4InfoParserException {
456 if (!COUNTER_UNIT_MAP.containsKey(spec.getUnit())) {
457 throw new P4InfoParserException(format(
458 "Unrecognized counter unit '%s'", spec.getUnit()));
459 }
460 return COUNTER_UNIT_MAP.get(spec.getUnit());
461 }
462
463 private static PiMeterModel.Unit mapMeterSpecUnit(MeterSpec spec)
464 throws P4InfoParserException {
465 if (!METER_UNIT_MAP.containsKey(spec.getUnit())) {
466 throw new P4InfoParserException(format(
467 "Unrecognized meter unit '%s'", spec.getUnit()));
468 }
469 return METER_UNIT_MAP.get(spec.getUnit());
470 }
471
472 private static PiPacketOperationType mapPacketOpType(String name)
473 throws P4InfoParserException {
474 if (!PACKET_OPERATION_TYPE_MAP.containsKey(name)) {
475 throw new P4InfoParserException(format(
476 "Unrecognized controller packet metadata name '%s'", name));
477 }
478 return PACKET_OPERATION_TYPE_MAP.get(name);
479 }
480
481 private static PiMatchType mapMatchFieldType(MatchField.MatchType type)
482 throws P4InfoParserException {
483 if (!MATCH_TYPE_MAP.containsKey(type)) {
484 throw new P4InfoParserException(format(
485 "Unrecognized match field type '%s'", type));
486 }
487 return MATCH_TYPE_MAP.get(type);
488 }
Carmelo Casconea3635ab2019-03-19 12:55:34 -0700489
Daniele Moro5c82b0f2020-12-07 20:56:30 +0100490 private static boolean isFieldString(P4Info p4info, String fieldTypeName) {
491 P4Types.P4TypeInfo p4TypeInfo = p4info.getTypeInfo();
492 return p4TypeInfo.containsNewTypes(fieldTypeName) &&
493 p4TypeInfo.getNewTypesOrThrow(fieldTypeName).hasTranslatedType() &&
494 p4TypeInfo.getNewTypesOrThrow(fieldTypeName).getTranslatedType().hasSdnString();
495 }
Carmelo Cascone87892e22017-11-13 16:01:29 -0800496}