use of p4.config.v1.P4InfoOuterClass.Table in project onos by opennetworkinglab.
the class FieldMatchCodec method encode.
@Override
public P4RuntimeOuterClass.FieldMatch encode(PiFieldMatch piFieldMatch, P4InfoOuterClass.Preamble tablePreamble, PiPipeconf pipeconf, P4InfoBrowser browser) throws CodecException, P4InfoBrowser.NotFoundException {
P4RuntimeOuterClass.FieldMatch.Builder messageBuilder = P4RuntimeOuterClass.FieldMatch.newBuilder();
// FIXME: check how field names for stacked headers are constructed in P4Runtime.
String fieldName = piFieldMatch.fieldId().id();
P4InfoOuterClass.MatchField matchFieldInfo = browser.matchFields(tablePreamble.getId()).getByName(fieldName);
String entityName = format("field match '%s' of table '%s'", matchFieldInfo.getName(), tablePreamble.getName());
int fieldId = matchFieldInfo.getId();
int fieldBitwidth = matchFieldInfo.getBitwidth();
boolean isSdnString = browser.isTypeString(matchFieldInfo.getTypeName());
messageBuilder.setFieldId(fieldId);
switch(piFieldMatch.type()) {
case EXACT:
PiExactFieldMatch fieldMatch = (PiExactFieldMatch) piFieldMatch;
ByteString exactValue = ByteString.copyFrom(fieldMatch.value().asReadOnlyBuffer());
if (!isSdnString) {
assertSize(VALUE_OF_PREFIX + entityName, exactValue, fieldBitwidth);
}
return messageBuilder.setExact(P4RuntimeOuterClass.FieldMatch.Exact.newBuilder().setValue(exactValue).build()).build();
case TERNARY:
PiTernaryFieldMatch ternaryMatch = (PiTernaryFieldMatch) piFieldMatch;
ByteString ternaryValue = ByteString.copyFrom(ternaryMatch.value().asReadOnlyBuffer());
ByteString ternaryMask = ByteString.copyFrom(ternaryMatch.mask().asReadOnlyBuffer());
if (isSdnString) {
sdnStringUnsupported(entityName, piFieldMatch.type());
}
assertSize(VALUE_OF_PREFIX + entityName, ternaryValue, fieldBitwidth);
assertSize(MASK_OF_PREFIX + entityName, ternaryMask, fieldBitwidth);
return messageBuilder.setTernary(P4RuntimeOuterClass.FieldMatch.Ternary.newBuilder().setValue(ternaryValue).setMask(ternaryMask).build()).build();
case LPM:
PiLpmFieldMatch lpmMatch = (PiLpmFieldMatch) piFieldMatch;
ByteString lpmValue = ByteString.copyFrom(lpmMatch.value().asReadOnlyBuffer());
int lpmPrefixLen = lpmMatch.prefixLength();
if (isSdnString) {
sdnStringUnsupported(entityName, piFieldMatch.type());
}
assertSize(VALUE_OF_PREFIX + entityName, lpmValue, fieldBitwidth);
assertPrefixLen(entityName, lpmPrefixLen, fieldBitwidth);
return messageBuilder.setLpm(P4RuntimeOuterClass.FieldMatch.LPM.newBuilder().setValue(lpmValue).setPrefixLen(lpmPrefixLen).build()).build();
case RANGE:
PiRangeFieldMatch rangeMatch = (PiRangeFieldMatch) piFieldMatch;
ByteString rangeHighValue = ByteString.copyFrom(rangeMatch.highValue().asReadOnlyBuffer());
ByteString rangeLowValue = ByteString.copyFrom(rangeMatch.lowValue().asReadOnlyBuffer());
if (isSdnString) {
sdnStringUnsupported(entityName, piFieldMatch.type());
}
assertSize(HIGH_RANGE_VALUE_OF_PREFIX + entityName, rangeHighValue, fieldBitwidth);
assertSize(LOW_RANGE_VALUE_OF_PREFIX + entityName, rangeLowValue, fieldBitwidth);
return messageBuilder.setRange(P4RuntimeOuterClass.FieldMatch.Range.newBuilder().setHigh(rangeHighValue).setLow(rangeLowValue).build()).build();
case OPTIONAL:
PiOptionalFieldMatch optionalMatch = (PiOptionalFieldMatch) piFieldMatch;
ByteString optionalValue = ByteString.copyFrom(optionalMatch.value().asReadOnlyBuffer());
if (!isSdnString) {
assertSize(VALUE_OF_PREFIX + entityName, optionalValue, fieldBitwidth);
}
return messageBuilder.setOptional(P4RuntimeOuterClass.FieldMatch.Optional.newBuilder().setValue(optionalValue).build()).build();
default:
throw new CodecException(format("Building of match type %s not implemented", piFieldMatch.type()));
}
}
use of p4.config.v1.P4InfoOuterClass.Table in project onos by opennetworkinglab.
the class P4InfoParser method parse.
/**
* Parse the given URL pointing to a P4Info file (in text format) to a PI pipeline model.
*
* @param p4InfoUrl URL to P4Info in text form
* @return PI pipeline model
* @throws P4InfoParserException if the P4Info file cannot be parsed (see message)
*/
public static PiPipelineModel parse(URL p4InfoUrl) throws P4InfoParserException {
final P4Info p4info;
try {
p4info = getP4InfoMessage(p4InfoUrl);
} catch (IOException e) {
throw new P4InfoParserException("Unable to parse protobuf " + p4InfoUrl.toString(), e);
}
// Generate fingerprint of the pipeline by hashing p4info file
final int fingerprint;
try {
HashingInputStream hin = new HashingInputStream(Hashing.crc32(), p4InfoUrl.openStream());
// noinspection StatementWithEmptyBody
while (hin.read() != -1) {
// Do nothing. Reading all input stream to update hash.
}
fingerprint = hin.hash().asInt();
} catch (IOException e) {
throw new P4InfoParserException("Unable to generate fingerprint " + p4InfoUrl.toString(), e);
}
// Start by parsing and mapping instances to to their integer P4Info IDs.
// Convenient to build the table model at the end.
final String architecture = parseArchitecture(p4info);
// Counters.
final Map<Integer, PiCounterModel> counterMap = Maps.newHashMap();
counterMap.putAll(parseCounters(p4info));
counterMap.putAll(parseDirectCounters(p4info));
// Meters.
final Map<Integer, PiMeterModel> meterMap = Maps.newHashMap();
meterMap.putAll(parseMeters(p4info));
meterMap.putAll(parseDirectMeters(p4info));
// Registers.
final Map<Integer, PiRegisterModel> registerMap = Maps.newHashMap();
registerMap.putAll(parseRegisters(p4info));
// Action profiles.
final Map<Integer, PiActionProfileModel> actProfileMap = parseActionProfiles(p4info);
// Actions.
final Map<Integer, PiActionModel> actionMap = parseActions(p4info);
// Controller packet metadatas.
final Map<PiPacketOperationType, PiPacketOperationModel> pktOpMap = parseCtrlPktMetadatas(p4info);
// Finally, parse tables.
final ImmutableMap.Builder<PiTableId, PiTableModel> tableImmMapBuilder = ImmutableMap.builder();
for (Table tableMsg : p4info.getTablesList()) {
final PiTableId tableId = PiTableId.of(tableMsg.getPreamble().getName());
// Parse match fields.
final ImmutableMap.Builder<PiMatchFieldId, PiMatchFieldModel> tableFieldMapBuilder = ImmutableMap.builder();
for (MatchField fieldMsg : tableMsg.getMatchFieldsList()) {
final PiMatchFieldId fieldId = PiMatchFieldId.of(fieldMsg.getName());
tableFieldMapBuilder.put(fieldId, new P4MatchFieldModel(fieldId, isFieldString(p4info, fieldMsg.getTypeName().getName()) ? P4MatchFieldModel.BIT_WIDTH_UNDEFINED : fieldMsg.getBitwidth(), mapMatchFieldType(fieldMsg.getMatchType())));
}
// Retrieve action models by inter IDs.
final ImmutableMap.Builder<PiActionId, PiActionModel> tableActionMapBuilder = ImmutableMap.builder();
tableMsg.getActionRefsList().stream().map(ActionRef::getId).map(actionMap::get).forEach(actionModel -> tableActionMapBuilder.put(actionModel.id(), actionModel));
// Retrieve direct meters by integer IDs.
final ImmutableMap.Builder<PiMeterId, PiMeterModel> tableMeterMapBuilder = ImmutableMap.builder();
tableMsg.getDirectResourceIdsList().stream().map(meterMap::get).filter(Objects::nonNull).forEach(meterModel -> tableMeterMapBuilder.put(meterModel.id(), meterModel));
// Retrieve direct counters by integer IDs.
final ImmutableMap.Builder<PiCounterId, PiCounterModel> tableCounterMapBuilder = ImmutableMap.builder();
tableMsg.getDirectResourceIdsList().stream().map(counterMap::get).filter(Objects::nonNull).forEach(counterModel -> tableCounterMapBuilder.put(counterModel.id(), counterModel));
// Check if table supports one-shot only
boolean oneShotOnly = isAnnotationPresent(ONE_SHOT_ONLY_ANNOTATION, tableMsg.getPreamble());
tableImmMapBuilder.put(tableId, new P4TableModel(PiTableId.of(tableMsg.getPreamble().getName()), tableMsg.getImplementationId() == 0 ? PiTableType.DIRECT : PiTableType.INDIRECT, actProfileMap.get(tableMsg.getImplementationId()), tableMsg.getSize(), tableCounterMapBuilder.build(), tableMeterMapBuilder.build(), !tableMsg.getIdleTimeoutBehavior().equals(Table.IdleTimeoutBehavior.NO_TIMEOUT), tableFieldMapBuilder.build(), tableActionMapBuilder.build(), actionMap.get(tableMsg.getConstDefaultActionId()), tableMsg.getIsConstTable(), oneShotOnly));
}
// Get a map with proper PI IDs for some of those maps we created at the beginning.
ImmutableMap<PiCounterId, PiCounterModel> counterImmMap = ImmutableMap.copyOf(counterMap.values().stream().collect(Collectors.toMap(PiCounterModel::id, c -> c)));
ImmutableMap<PiMeterId, PiMeterModel> meterImmMap = ImmutableMap.copyOf(meterMap.values().stream().collect(Collectors.toMap(PiMeterModel::id, m -> m)));
ImmutableMap<PiRegisterId, PiRegisterModel> registerImmMap = ImmutableMap.copyOf(registerMap.values().stream().collect(Collectors.toMap(PiRegisterModel::id, r -> r)));
ImmutableMap<PiActionProfileId, PiActionProfileModel> actProfileImmMap = ImmutableMap.copyOf(actProfileMap.values().stream().collect(Collectors.toMap(PiActionProfileModel::id, a -> a)));
return new P4PipelineModel(tableImmMapBuilder.build(), counterImmMap, meterImmMap, registerImmMap, actProfileImmMap, ImmutableMap.copyOf(pktOpMap), architecture, fingerprint);
}
use of p4.config.v1.P4InfoOuterClass.Table in project onos by opennetworkinglab.
the class P4InfoParserTest method testParse.
/**
* Tests parse method.
* @throws Exception if equality group objects dose not match as expected
*/
@Test
public void testParse() throws Exception {
// Generate two PiPipelineModels from the same p4Info file
PiPipelineModel model = P4InfoParser.parse(p4InfoUrl);
PiPipelineModel sameAsModel = P4InfoParser.parse(p4InfoUrl);
// Check equality
new EqualsTester().addEqualityGroup(model, sameAsModel).testEquals();
// Generate a P4Info object from the file
final P4Info p4info;
try {
p4info = getP4InfoMessage(p4InfoUrl);
} catch (IOException e) {
throw new P4InfoParserException("Unable to parse protobuf " + p4InfoUrl.toString(), e);
}
List<Table> tableMsgs = p4info.getTablesList();
PiTableId table0Id = PiTableId.of(tableMsgs.get(0).getPreamble().getName());
PiTableId wcmpTableId = PiTableId.of(tableMsgs.get(1).getPreamble().getName());
PiTableId wcmpTableOneShotId = PiTableId.of(tableMsgs.get(2).getPreamble().getName());
// parse tables
PiTableModel table0Model = model.table(table0Id).orElse(null);
PiTableModel wcmpTableModel = model.table(wcmpTableId).orElse(null);
PiTableModel wcmpTableOneShotModel = model.table(wcmpTableOneShotId).orElse(null);
PiTableModel table0Model2 = sameAsModel.table(table0Id).orElse(null);
PiTableModel wcmpTableModel2 = sameAsModel.table(wcmpTableId).orElse(null);
new EqualsTester().addEqualityGroup(table0Model, table0Model2).addEqualityGroup(wcmpTableModel, wcmpTableModel2).testEquals();
// Check existence
assertThat("model parsed value is null", table0Model, notNullValue());
assertThat("model parsed value is null", wcmpTableModel, notNullValue());
assertThat("model parsed value is null", wcmpTableOneShotModel, notNullValue());
assertThat("Incorrect size for table0 size", table0Model.maxSize(), is(equalTo(DEFAULT_MAX_TABLE_SIZE)));
assertThat("Incorrect size for wcmp_table size", wcmpTableModel.maxSize(), is(equalTo(DEFAULT_MAX_TABLE_SIZE)));
assertThat("Incorrect size for wcmp_table_one_shot size", wcmpTableOneShotModel.maxSize(), is(equalTo(DEFAULT_MAX_TABLE_SIZE)));
// Check one-shot annotation
assertThat("error parsing one-shot annotation", wcmpTableModel.oneShotOnly(), is(false));
assertThat("error parsing one-shot annotation", wcmpTableOneShotModel.oneShotOnly(), is(true));
// Check matchFields
List<MatchField> matchFieldList = tableMsgs.get(0).getMatchFieldsList();
List<PiMatchFieldModel> piMatchFieldList = new ArrayList<>();
for (MatchField matchFieldIter : matchFieldList) {
MatchField.MatchType matchType = matchFieldIter.getMatchType();
PiMatchType piMatchType;
switch(matchType) {
case EXACT:
piMatchType = PiMatchType.EXACT;
break;
case LPM:
piMatchType = PiMatchType.LPM;
break;
case TERNARY:
piMatchType = PiMatchType.TERNARY;
break;
case RANGE:
piMatchType = PiMatchType.RANGE;
break;
default:
Assert.fail();
return;
}
piMatchFieldList.add(new P4MatchFieldModel(PiMatchFieldId.of(matchFieldIter.getName()), matchFieldIter.getBitwidth(), piMatchType));
}
// Check MatchFields size
assertThat("Incorrect size for matchFields", table0Model.matchFields().size(), is(equalTo(9)));
// Check if matchFields are in order
assertThat("Incorrect order for matchFields", table0Model.matchFields(), IsIterableContainingInOrder.contains(piMatchFieldList.get(0), piMatchFieldList.get(1), piMatchFieldList.get(2), piMatchFieldList.get(3), piMatchFieldList.get(4), piMatchFieldList.get(5), piMatchFieldList.get(6), piMatchFieldList.get(7), piMatchFieldList.get(8)));
assertThat("Incorrect size for matchFields", wcmpTableModel.matchFields().size(), is(equalTo(1)));
// check if matchFields are in order
matchFieldList = tableMsgs.get(1).getMatchFieldsList();
assertThat("Incorrect order for matchFields", wcmpTableModel.matchFields(), IsIterableContainingInOrder.contains(new P4MatchFieldModel(PiMatchFieldId.of(matchFieldList.get(0).getName()), matchFieldList.get(0).getBitwidth(), PiMatchType.EXACT)));
// check table0 actionsRefs
List<ActionRef> actionRefList = tableMsgs.get(0).getActionRefsList();
assertThat("Incorrect size for actionRefs", actionRefList.size(), is(equalTo(4)));
// create action instances
PiActionId actionId = PiActionId.of("set_egress_port");
PiActionParamId piActionParamId = PiActionParamId.of("port");
int bitWitdth = 9;
PiActionParamModel actionParamModel = new P4ActionParamModel(piActionParamId, bitWitdth);
ImmutableMap<PiActionParamId, PiActionParamModel> params = new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>().put(piActionParamId, actionParamModel).build();
PiActionModel setEgressPortAction = new P4ActionModel(actionId, params);
actionId = PiActionId.of("send_to_cpu");
PiActionModel sendToCpuAction = new P4ActionModel(actionId, new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>().build());
actionId = PiActionId.of("_drop");
PiActionModel dropAction = new P4ActionModel(actionId, new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>().build());
actionId = PiActionId.of("NoAction");
PiActionModel noAction = new P4ActionModel(actionId, new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>().build());
actionId = PiActionId.of("table0_control.set_next_hop_id");
piActionParamId = PiActionParamId.of("next_hop_id");
bitWitdth = 16;
actionParamModel = new P4ActionParamModel(piActionParamId, bitWitdth);
params = new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>().put(piActionParamId, actionParamModel).build();
PiActionModel setNextHopIdAction = new P4ActionModel(actionId, params);
// check table0 actions
assertThat("action dose not match", table0Model.actions(), IsIterableContainingInAnyOrder.containsInAnyOrder(setEgressPortAction, sendToCpuAction, setNextHopIdAction, dropAction));
// check wcmp_table actions
assertThat("actions dose not match", wcmpTableModel.actions(), IsIterableContainingInAnyOrder.containsInAnyOrder(setEgressPortAction, noAction));
PiActionModel table0DefaultAction = table0Model.constDefaultAction().orElse(null);
new EqualsTester().addEqualityGroup(table0DefaultAction, dropAction).testEquals();
// Check existence
assertThat("model parsed value is null", table0DefaultAction, notNullValue());
// parse action profiles
PiTableId tableId = PiTableId.of("wcmp_control.wcmp_table");
ImmutableSet<PiTableId> tableIds = new ImmutableSet.Builder<PiTableId>().add(tableId).build();
PiActionProfileId actionProfileId = PiActionProfileId.of("wcmp_control.wcmp_selector");
PiActionProfileModel wcmpSelector3 = new P4ActionProfileModel(actionProfileId, tableIds, true, DEFAULT_MAX_ACTION_PROFILE_SIZE, DEFAULT_MAX_GROUP_SIZE);
PiActionProfileModel wcmpSelector = model.actionProfiles(actionProfileId).orElse(null);
PiActionProfileModel wcmpSelector2 = sameAsModel.actionProfiles(actionProfileId).orElse(null);
new EqualsTester().addEqualityGroup(wcmpSelector, wcmpSelector2, wcmpSelector3).testEquals();
// Check existence
assertThat("model parsed value is null", wcmpSelector, notNullValue());
assertThat("Incorrect value for actions profiles", model.actionProfiles(), containsInAnyOrder(wcmpSelector));
// ActionProfiles size
assertThat("Incorrect size for action profiles", model.actionProfiles().size(), is(equalTo(1)));
// parse counters
PiCounterModel ingressPortCounterModel = model.counter(PiCounterId.of("port_counters_ingress.ingress_port_counter")).orElse(null);
PiCounterModel egressPortCounterModel = model.counter(PiCounterId.of("port_counters_egress.egress_port_counter")).orElse(null);
PiCounterModel table0CounterModel = model.counter(PiCounterId.of("table0_control.table0_counter")).orElse(null);
PiCounterModel wcmpTableCounterModel = model.counter(PiCounterId.of("wcmp_control.wcmp_table_counter")).orElse(null);
PiCounterModel ingressPortCounterModel2 = sameAsModel.counter(PiCounterId.of("port_counters_ingress.ingress_port_counter")).orElse(null);
PiCounterModel egressPortCounterModel2 = sameAsModel.counter(PiCounterId.of("port_counters_egress.egress_port_counter")).orElse(null);
PiCounterModel table0CounterModel2 = sameAsModel.counter(PiCounterId.of("table0_control.table0_counter")).orElse(null);
PiCounterModel wcmpTableCounterModel2 = sameAsModel.counter(PiCounterId.of("wcmp_control.wcmp_table_counter")).orElse(null);
new EqualsTester().addEqualityGroup(ingressPortCounterModel, ingressPortCounterModel2).addEqualityGroup(egressPortCounterModel, egressPortCounterModel2).addEqualityGroup(table0CounterModel, table0CounterModel2).addEqualityGroup(wcmpTableCounterModel, wcmpTableCounterModel2).testEquals();
assertThat("model parsed value is null", ingressPortCounterModel, notNullValue());
assertThat("model parsed value is null", egressPortCounterModel, notNullValue());
assertThat("model parsed value is null", table0CounterModel, notNullValue());
assertThat("model parsed value is null", wcmpTableCounterModel, notNullValue());
// Parse meters
Collection<PiMeterModel> meterModel = model.meters();
Collection<PiMeterModel> meterModel2 = sameAsModel.meters();
assertThat("model parsed meter collection should be empty", meterModel.isEmpty(), is(true));
assertThat("model parsed meter collection should be empty", meterModel2.isEmpty(), is(true));
// parse packet operations
PiPacketOperationModel packetInOperationalModel = model.packetOperationModel(PiPacketOperationType.PACKET_IN).orElse(null);
PiPacketOperationModel packetOutOperationalModel = model.packetOperationModel(PiPacketOperationType.PACKET_OUT).orElse(null);
PiPacketOperationModel packetInOperationalModel2 = sameAsModel.packetOperationModel(PiPacketOperationType.PACKET_IN).orElse(null);
PiPacketOperationModel packetOutOperationalModel2 = sameAsModel.packetOperationModel(PiPacketOperationType.PACKET_OUT).orElse(null);
new EqualsTester().addEqualityGroup(packetInOperationalModel, packetInOperationalModel2).addEqualityGroup(packetOutOperationalModel, packetOutOperationalModel2).testEquals();
// Check existence
assertThat("model parsed value is null", packetInOperationalModel, notNullValue());
assertThat("model parsed value is null", packetOutOperationalModel, notNullValue());
}
use of p4.config.v1.P4InfoOuterClass.Table in project onos by opennetworkinglab.
the class TableEntryEncoderTest method testTableEntryEncoder.
@Test
public void testTableEntryEncoder() throws Exception {
TableEntry tableEntryMsg = Codecs.CODECS.tableEntry().encode(piTableEntry, null, defaultPipeconf);
PiTableEntry decodedPiTableEntry = Codecs.CODECS.tableEntry().decode(tableEntryMsg, null, defaultPipeconf);
// Test equality for decoded entry.
new EqualsTester().addEqualityGroup(piTableEntry, decodedPiTableEntry).testEquals();
// Table ID.
int p4InfoTableId = browser.tables().getByName(tableId.id()).getPreamble().getId();
int encodedTableId = tableEntryMsg.getTableId();
assertThat(encodedTableId, is(p4InfoTableId));
// Ternary match.
byte[] encodedTernaryMatchValue = tableEntryMsg.getMatch(0).getTernary().getValue().toByteArray();
assertThat(encodedTernaryMatchValue, is(ethAddr.asArray()));
Action actionMsg = tableEntryMsg.getAction().getAction();
// Action ID.
int p4InfoActionId = browser.actions().getByName(outActionId.toString()).getPreamble().getId();
int encodedActionId = actionMsg.getActionId();
assertThat(encodedActionId, is(p4InfoActionId));
// Action param ID.
int p4InfoActionParamId = browser.actionParams(p4InfoActionId).getByName(portParamId.toString()).getId();
int encodedActionParamId = actionMsg.getParams(0).getParamId();
assertThat(encodedActionParamId, is(p4InfoActionParamId));
// Action param value.
byte[] encodedActionParam = actionMsg.getParams(0).getValue().toByteArray();
assertThat(encodedActionParam, is(portValue.asArray()));
// Counter
CounterData counterData = tableEntryMsg.getCounterData();
PiCounterCellData encodedCounterData = new PiCounterCellData(counterData.getPacketCount(), counterData.getByteCount());
assertThat(encodedCounterData, is(counterCellData));
// TODO: improve, assert other field match types (ternary, LPM)
}
Aggregations