blob: 5e2ec438c9af55814a7e7ff600ceac30e5d95eb0 [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 com.google.protobuf.ByteString;
20import org.onlab.util.ImmutableByteSequence;
21import org.onosproject.net.pi.model.PiMatchFieldId;
22import org.onosproject.net.pi.model.PiPipeconf;
23import org.onosproject.net.pi.runtime.PiExactFieldMatch;
24import org.onosproject.net.pi.runtime.PiFieldMatch;
25import org.onosproject.net.pi.runtime.PiLpmFieldMatch;
26import org.onosproject.net.pi.runtime.PiRangeFieldMatch;
27import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
28import org.onosproject.p4runtime.ctl.utils.P4InfoBrowser;
29import p4.config.v1.P4InfoOuterClass;
30import p4.v1.P4RuntimeOuterClass;
31
32import static java.lang.String.format;
33import static org.onlab.util.ImmutableByteSequence.copyFrom;
34import static org.onosproject.p4runtime.ctl.codec.Utils.assertPrefixLen;
35import static org.onosproject.p4runtime.ctl.codec.Utils.assertSize;
36
37/**
38 * Codec for P4Runtime FieldMatch. Metadata is expected to be a Preamble for
39 * P4Info.Table.
40 */
41public final class FieldMatchCodec
42 extends AbstractCodec<PiFieldMatch, P4RuntimeOuterClass.FieldMatch,
43 P4InfoOuterClass.Preamble> {
44
45 private static final String VALUE_OF_PREFIX = "value of ";
46 private static final String MASK_OF_PREFIX = "mask of ";
47 private static final String HIGH_RANGE_VALUE_OF_PREFIX = "high range value of ";
48 private static final String LOW_RANGE_VALUE_OF_PREFIX = "low range value of ";
49
50 @Override
51 public P4RuntimeOuterClass.FieldMatch encode(
52 PiFieldMatch piFieldMatch, P4InfoOuterClass.Preamble tablePreamble,
53 PiPipeconf pipeconf, P4InfoBrowser browser)
54 throws CodecException, P4InfoBrowser.NotFoundException {
55
56 P4RuntimeOuterClass.FieldMatch.Builder messageBuilder = P4RuntimeOuterClass
57 .FieldMatch.newBuilder();
58
59 // FIXME: check how field names for stacked headers are constructed in P4Runtime.
60 String fieldName = piFieldMatch.fieldId().id();
61 P4InfoOuterClass.MatchField matchFieldInfo = browser.matchFields(
62 tablePreamble.getId()).getByName(fieldName);
63 String entityName = format("field match '%s' of table '%s'",
64 matchFieldInfo.getName(), tablePreamble.getName());
65 int fieldId = matchFieldInfo.getId();
66 int fieldBitwidth = matchFieldInfo.getBitwidth();
67
68 messageBuilder.setFieldId(fieldId);
69
70 switch (piFieldMatch.type()) {
71 case EXACT:
72 PiExactFieldMatch fieldMatch = (PiExactFieldMatch) piFieldMatch;
73 ByteString exactValue = ByteString.copyFrom(fieldMatch.value().asReadOnlyBuffer());
Daniele Moro5c82b0f2020-12-07 20:56:30 +010074 // We support string only for EXACT match (via p4runtime_translation)
75 if (!browser.isTypeString(matchFieldInfo.getTypeName())) {
76 assertSize(VALUE_OF_PREFIX + entityName, exactValue, fieldBitwidth);
77 }
Carmelo Cascone4c289b72019-01-22 15:30:45 -080078 return messageBuilder.setExact(
79 P4RuntimeOuterClass.FieldMatch.Exact
80 .newBuilder()
81 .setValue(exactValue)
82 .build())
83 .build();
84 case TERNARY:
85 PiTernaryFieldMatch ternaryMatch = (PiTernaryFieldMatch) piFieldMatch;
86 ByteString ternaryValue = ByteString.copyFrom(ternaryMatch.value().asReadOnlyBuffer());
87 ByteString ternaryMask = ByteString.copyFrom(ternaryMatch.mask().asReadOnlyBuffer());
88 assertSize(VALUE_OF_PREFIX + entityName, ternaryValue, fieldBitwidth);
89 assertSize(MASK_OF_PREFIX + entityName, ternaryMask, fieldBitwidth);
90 return messageBuilder.setTernary(
91 P4RuntimeOuterClass.FieldMatch.Ternary
92 .newBuilder()
93 .setValue(ternaryValue)
94 .setMask(ternaryMask)
95 .build())
96 .build();
97 case LPM:
98 PiLpmFieldMatch lpmMatch = (PiLpmFieldMatch) piFieldMatch;
99 ByteString lpmValue = ByteString.copyFrom(lpmMatch.value().asReadOnlyBuffer());
100 int lpmPrefixLen = lpmMatch.prefixLength();
101 assertSize(VALUE_OF_PREFIX + entityName, lpmValue, fieldBitwidth);
102 assertPrefixLen(entityName, lpmPrefixLen, fieldBitwidth);
103 return messageBuilder.setLpm(
104 P4RuntimeOuterClass.FieldMatch.LPM.newBuilder()
105 .setValue(lpmValue)
106 .setPrefixLen(lpmPrefixLen)
107 .build())
108 .build();
109 case RANGE:
110 PiRangeFieldMatch rangeMatch = (PiRangeFieldMatch) piFieldMatch;
111 ByteString rangeHighValue = ByteString.copyFrom(rangeMatch.highValue().asReadOnlyBuffer());
112 ByteString rangeLowValue = ByteString.copyFrom(rangeMatch.lowValue().asReadOnlyBuffer());
113 assertSize(HIGH_RANGE_VALUE_OF_PREFIX + entityName, rangeHighValue, fieldBitwidth);
114 assertSize(LOW_RANGE_VALUE_OF_PREFIX + entityName, rangeLowValue, fieldBitwidth);
115 return messageBuilder.setRange(
116 P4RuntimeOuterClass.FieldMatch.Range.newBuilder()
117 .setHigh(rangeHighValue)
118 .setLow(rangeLowValue)
119 .build())
120 .build();
121 default:
122 throw new CodecException(format(
123 "Building of match type %s not implemented", piFieldMatch.type()));
124 }
125 }
126
127 @Override
128 public PiFieldMatch decode(
129 P4RuntimeOuterClass.FieldMatch message, P4InfoOuterClass.Preamble tablePreamble,
130 PiPipeconf pipeconf, P4InfoBrowser browser)
131 throws CodecException, P4InfoBrowser.NotFoundException {
132
133 String fieldMatchName = browser.matchFields(tablePreamble.getId())
134 .getById(message.getFieldId()).getName();
135 PiMatchFieldId headerFieldId = PiMatchFieldId.of(fieldMatchName);
136
137 P4RuntimeOuterClass.FieldMatch.FieldMatchTypeCase typeCase = message.getFieldMatchTypeCase();
138
139 switch (typeCase) {
140 case EXACT:
141 P4RuntimeOuterClass.FieldMatch.Exact exactFieldMatch = message.getExact();
142 ImmutableByteSequence exactValue = copyFrom(exactFieldMatch.getValue().asReadOnlyByteBuffer());
143 return new PiExactFieldMatch(headerFieldId, exactValue);
144 case TERNARY:
145 P4RuntimeOuterClass.FieldMatch.Ternary ternaryFieldMatch = message.getTernary();
146 ImmutableByteSequence ternaryValue = copyFrom(ternaryFieldMatch.getValue().asReadOnlyByteBuffer());
147 ImmutableByteSequence ternaryMask = copyFrom(ternaryFieldMatch.getMask().asReadOnlyByteBuffer());
148 return new PiTernaryFieldMatch(headerFieldId, ternaryValue, ternaryMask);
149 case LPM:
150 P4RuntimeOuterClass.FieldMatch.LPM lpmFieldMatch = message.getLpm();
151 ImmutableByteSequence lpmValue = copyFrom(lpmFieldMatch.getValue().asReadOnlyByteBuffer());
152 int lpmPrefixLen = lpmFieldMatch.getPrefixLen();
153 return new PiLpmFieldMatch(headerFieldId, lpmValue, lpmPrefixLen);
154 case RANGE:
155 P4RuntimeOuterClass.FieldMatch.Range rangeFieldMatch = message.getRange();
156 ImmutableByteSequence rangeHighValue = copyFrom(rangeFieldMatch.getHigh().asReadOnlyByteBuffer());
157 ImmutableByteSequence rangeLowValue = copyFrom(rangeFieldMatch.getLow().asReadOnlyByteBuffer());
158 return new PiRangeFieldMatch(headerFieldId, rangeLowValue, rangeHighValue);
159 default:
160 throw new CodecException(format(
161 "Decoding of field match type '%s' not implemented", typeCase.name()));
162 }
163 }
164}