blob: 6b015466ae3a914a2617ddba781a6bf5f455853d [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;
Daniele Moroc6f2f7f2020-12-18 10:55:57 +010026import org.onosproject.net.pi.runtime.PiOptionalFieldMatch;
Carmelo Cascone4c289b72019-01-22 15:30:45 -080027import org.onosproject.net.pi.runtime.PiRangeFieldMatch;
28import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
29import org.onosproject.p4runtime.ctl.utils.P4InfoBrowser;
30import p4.config.v1.P4InfoOuterClass;
31import p4.v1.P4RuntimeOuterClass;
32
33import static java.lang.String.format;
34import static org.onlab.util.ImmutableByteSequence.copyFrom;
35import static org.onosproject.p4runtime.ctl.codec.Utils.assertPrefixLen;
36import static org.onosproject.p4runtime.ctl.codec.Utils.assertSize;
Daniele Moroc6f2f7f2020-12-18 10:55:57 +010037import static org.onosproject.p4runtime.ctl.codec.Utils.sdnStringUnsupported;
Carmelo Cascone4c289b72019-01-22 15:30:45 -080038
39/**
40 * Codec for P4Runtime FieldMatch. Metadata is expected to be a Preamble for
41 * P4Info.Table.
42 */
43public final class FieldMatchCodec
44 extends AbstractCodec<PiFieldMatch, P4RuntimeOuterClass.FieldMatch,
45 P4InfoOuterClass.Preamble> {
46
47 private static final String VALUE_OF_PREFIX = "value of ";
48 private static final String MASK_OF_PREFIX = "mask of ";
49 private static final String HIGH_RANGE_VALUE_OF_PREFIX = "high range value of ";
50 private static final String LOW_RANGE_VALUE_OF_PREFIX = "low range value of ";
51
52 @Override
53 public P4RuntimeOuterClass.FieldMatch encode(
54 PiFieldMatch piFieldMatch, P4InfoOuterClass.Preamble tablePreamble,
55 PiPipeconf pipeconf, P4InfoBrowser browser)
56 throws CodecException, P4InfoBrowser.NotFoundException {
57
58 P4RuntimeOuterClass.FieldMatch.Builder messageBuilder = P4RuntimeOuterClass
59 .FieldMatch.newBuilder();
60
61 // FIXME: check how field names for stacked headers are constructed in P4Runtime.
62 String fieldName = piFieldMatch.fieldId().id();
63 P4InfoOuterClass.MatchField matchFieldInfo = browser.matchFields(
64 tablePreamble.getId()).getByName(fieldName);
65 String entityName = format("field match '%s' of table '%s'",
66 matchFieldInfo.getName(), tablePreamble.getName());
67 int fieldId = matchFieldInfo.getId();
68 int fieldBitwidth = matchFieldInfo.getBitwidth();
Daniele Moroc6f2f7f2020-12-18 10:55:57 +010069 boolean isSdnString = browser.isTypeString(matchFieldInfo.getTypeName());
Carmelo Cascone4c289b72019-01-22 15:30:45 -080070
71 messageBuilder.setFieldId(fieldId);
72
73 switch (piFieldMatch.type()) {
74 case EXACT:
75 PiExactFieldMatch fieldMatch = (PiExactFieldMatch) piFieldMatch;
76 ByteString exactValue = ByteString.copyFrom(fieldMatch.value().asReadOnlyBuffer());
Daniele Moroc6f2f7f2020-12-18 10:55:57 +010077 if (!isSdnString) {
Daniele Moro5c82b0f2020-12-07 20:56:30 +010078 assertSize(VALUE_OF_PREFIX + entityName, exactValue, fieldBitwidth);
79 }
Carmelo Cascone4c289b72019-01-22 15:30:45 -080080 return messageBuilder.setExact(
81 P4RuntimeOuterClass.FieldMatch.Exact
82 .newBuilder()
83 .setValue(exactValue)
84 .build())
85 .build();
86 case TERNARY:
87 PiTernaryFieldMatch ternaryMatch = (PiTernaryFieldMatch) piFieldMatch;
88 ByteString ternaryValue = ByteString.copyFrom(ternaryMatch.value().asReadOnlyBuffer());
89 ByteString ternaryMask = ByteString.copyFrom(ternaryMatch.mask().asReadOnlyBuffer());
Daniele Moroc6f2f7f2020-12-18 10:55:57 +010090 if (isSdnString) {
91 sdnStringUnsupported(entityName, piFieldMatch.type());
92 }
Carmelo Cascone4c289b72019-01-22 15:30:45 -080093 assertSize(VALUE_OF_PREFIX + entityName, ternaryValue, fieldBitwidth);
94 assertSize(MASK_OF_PREFIX + entityName, ternaryMask, fieldBitwidth);
95 return messageBuilder.setTernary(
96 P4RuntimeOuterClass.FieldMatch.Ternary
97 .newBuilder()
98 .setValue(ternaryValue)
99 .setMask(ternaryMask)
100 .build())
101 .build();
102 case LPM:
103 PiLpmFieldMatch lpmMatch = (PiLpmFieldMatch) piFieldMatch;
104 ByteString lpmValue = ByteString.copyFrom(lpmMatch.value().asReadOnlyBuffer());
105 int lpmPrefixLen = lpmMatch.prefixLength();
Daniele Moroc6f2f7f2020-12-18 10:55:57 +0100106 if (isSdnString) {
107 sdnStringUnsupported(entityName, piFieldMatch.type());
108 }
Carmelo Cascone4c289b72019-01-22 15:30:45 -0800109 assertSize(VALUE_OF_PREFIX + entityName, lpmValue, fieldBitwidth);
110 assertPrefixLen(entityName, lpmPrefixLen, fieldBitwidth);
111 return messageBuilder.setLpm(
112 P4RuntimeOuterClass.FieldMatch.LPM.newBuilder()
113 .setValue(lpmValue)
114 .setPrefixLen(lpmPrefixLen)
115 .build())
116 .build();
117 case RANGE:
118 PiRangeFieldMatch rangeMatch = (PiRangeFieldMatch) piFieldMatch;
119 ByteString rangeHighValue = ByteString.copyFrom(rangeMatch.highValue().asReadOnlyBuffer());
120 ByteString rangeLowValue = ByteString.copyFrom(rangeMatch.lowValue().asReadOnlyBuffer());
Daniele Moroc6f2f7f2020-12-18 10:55:57 +0100121 if (isSdnString) {
122 sdnStringUnsupported(entityName, piFieldMatch.type());
123 }
Carmelo Cascone4c289b72019-01-22 15:30:45 -0800124 assertSize(HIGH_RANGE_VALUE_OF_PREFIX + entityName, rangeHighValue, fieldBitwidth);
125 assertSize(LOW_RANGE_VALUE_OF_PREFIX + entityName, rangeLowValue, fieldBitwidth);
126 return messageBuilder.setRange(
127 P4RuntimeOuterClass.FieldMatch.Range.newBuilder()
128 .setHigh(rangeHighValue)
129 .setLow(rangeLowValue)
130 .build())
131 .build();
Daniele Moroc6f2f7f2020-12-18 10:55:57 +0100132 case OPTIONAL:
133 PiOptionalFieldMatch optionalMatch = (PiOptionalFieldMatch) piFieldMatch;
134 ByteString optionalValue = ByteString.copyFrom(optionalMatch.value().asReadOnlyBuffer());
135 if (!isSdnString) {
136 assertSize(VALUE_OF_PREFIX + entityName, optionalValue, fieldBitwidth);
137 }
138 return messageBuilder.setOptional(
139 P4RuntimeOuterClass.FieldMatch.Optional.newBuilder()
140 .setValue(optionalValue)
141 .build())
142 .build();
Carmelo Cascone4c289b72019-01-22 15:30:45 -0800143 default:
144 throw new CodecException(format(
145 "Building of match type %s not implemented", piFieldMatch.type()));
146 }
147 }
148
149 @Override
150 public PiFieldMatch decode(
151 P4RuntimeOuterClass.FieldMatch message, P4InfoOuterClass.Preamble tablePreamble,
152 PiPipeconf pipeconf, P4InfoBrowser browser)
153 throws CodecException, P4InfoBrowser.NotFoundException {
154
Daniele Moro7aa13e62021-02-23 15:28:07 +0100155 final P4InfoOuterClass.MatchField matchField =
156 browser.matchFields(tablePreamble.getId())
157 .getById(message.getFieldId());
158 final PiMatchFieldId headerFieldId = PiMatchFieldId.of(matchField.getName());
159 final boolean isSdnString = browser.isTypeString(matchField.getTypeName());
Carmelo Cascone4c289b72019-01-22 15:30:45 -0800160
161 P4RuntimeOuterClass.FieldMatch.FieldMatchTypeCase typeCase = message.getFieldMatchTypeCase();
162
163 switch (typeCase) {
164 case EXACT:
165 P4RuntimeOuterClass.FieldMatch.Exact exactFieldMatch = message.getExact();
Daniele Moro7aa13e62021-02-23 15:28:07 +0100166 ImmutableByteSequence exactValue;
167 if (isSdnString) {
168 exactValue = copyFrom(new String(exactFieldMatch.getValue().toByteArray()));
169 } else {
170 exactValue = copyFrom(exactFieldMatch.getValue().asReadOnlyByteBuffer());
171 }
Carmelo Cascone4c289b72019-01-22 15:30:45 -0800172 return new PiExactFieldMatch(headerFieldId, exactValue);
173 case TERNARY:
174 P4RuntimeOuterClass.FieldMatch.Ternary ternaryFieldMatch = message.getTernary();
175 ImmutableByteSequence ternaryValue = copyFrom(ternaryFieldMatch.getValue().asReadOnlyByteBuffer());
176 ImmutableByteSequence ternaryMask = copyFrom(ternaryFieldMatch.getMask().asReadOnlyByteBuffer());
177 return new PiTernaryFieldMatch(headerFieldId, ternaryValue, ternaryMask);
178 case LPM:
179 P4RuntimeOuterClass.FieldMatch.LPM lpmFieldMatch = message.getLpm();
180 ImmutableByteSequence lpmValue = copyFrom(lpmFieldMatch.getValue().asReadOnlyByteBuffer());
181 int lpmPrefixLen = lpmFieldMatch.getPrefixLen();
182 return new PiLpmFieldMatch(headerFieldId, lpmValue, lpmPrefixLen);
183 case RANGE:
184 P4RuntimeOuterClass.FieldMatch.Range rangeFieldMatch = message.getRange();
185 ImmutableByteSequence rangeHighValue = copyFrom(rangeFieldMatch.getHigh().asReadOnlyByteBuffer());
186 ImmutableByteSequence rangeLowValue = copyFrom(rangeFieldMatch.getLow().asReadOnlyByteBuffer());
187 return new PiRangeFieldMatch(headerFieldId, rangeLowValue, rangeHighValue);
Daniele Moroc6f2f7f2020-12-18 10:55:57 +0100188 case OPTIONAL:
189 P4RuntimeOuterClass.FieldMatch.Optional optionalFieldMatch = message.getOptional();
Daniele Moro7aa13e62021-02-23 15:28:07 +0100190 ImmutableByteSequence optionalValue;
191 if (isSdnString) {
192 optionalValue = copyFrom(new String(optionalFieldMatch.getValue().toByteArray()));
193 } else {
194 optionalValue = copyFrom(optionalFieldMatch.getValue().asReadOnlyByteBuffer());
195 }
Daniele Moroc6f2f7f2020-12-18 10:55:57 +0100196 return new PiOptionalFieldMatch(headerFieldId, optionalValue);
Carmelo Cascone4c289b72019-01-22 15:30:45 -0800197 default:
198 throw new CodecException(format(
199 "Decoding of field match type '%s' not implemented", typeCase.name()));
200 }
201 }
202}