Java源码示例:org.onosproject.net.pi.runtime.PiTableAction
示例1
/**
* Creates a routing flow rule that matches on the given IPv6 prefix and
* executes the given group ID (created before).
*
* @param deviceId the device where flow rule will be installed
* @param ip6Prefix the IPv6 prefix
* @param groupId the group ID
* @return a flow rule
*/
private FlowRule createRoutingRule(DeviceId deviceId, Ip6Prefix ip6Prefix,
int groupId) {
final String tableId = "IngressPipeImpl.routing_v6_table";
final PiCriterion match = PiCriterion.builder()
.matchLpm(
PiMatchFieldId.of("hdr.ipv6.dst_addr"),
ip6Prefix.address().toOctets(),
ip6Prefix.prefixLength())
.build();
final PiTableAction action = PiActionProfileGroupId.of(groupId);
return Utils.buildFlowRule(
deviceId, appId, tableId, match, action);
}
示例2
/**
* Creates a routing flow rule that matches on the given IPv6 prefix and
* executes the given group ID (created before).
*
* @param deviceId the device where flow rule will be installed
* @param ip6Prefix the IPv6 prefix
* @param groupId the group ID
* @return a flow rule
*/
private FlowRule createRoutingRule(DeviceId deviceId, Ip6Prefix ip6Prefix,
int groupId) {
// TODO EXERCISE 3
// Modify P4Runtime entity names to match content of P4Info file (look
// for the fully qualified name of tables, match fields, and actions.
// ---- START SOLUTION ----
final String tableId = "IngressPipeImpl.l3_table";
final PiCriterion match = PiCriterion.builder()
.matchLpm(
PiMatchFieldId.of("hdr.ipv6.dst_addr"),
ip6Prefix.address().toOctets(),
ip6Prefix.prefixLength())
.build();
final PiTableAction action = PiActionProfileGroupId.of(groupId);
// ---- END SOLUTION ----
return Utils.buildFlowRule(
deviceId, appId, tableId, match, action);
}
示例3
/**
* Creates a routing flow rule that matches on the given IPv6 prefix and
* executes the given group ID (created before).
*
* @param deviceId the device where flow rule will be installed
* @param ip6Prefix the IPv6 prefix
* @param groupId the group ID
* @return a flow rule
*/
private FlowRule createRoutingRule(DeviceId deviceId, Ip6Prefix ip6Prefix,
int groupId) {
// TODO EXERCISE 3
// Modify P4Runtime entity names to match content of P4Info file (look
// for the fully qualified name of tables, match fields, and actions.
// ---- START SOLUTION ----
final String tableId = "MODIFY ME";
final PiCriterion match = PiCriterion.builder()
.matchLpm(
PiMatchFieldId.of("MODIFY ME"),
ip6Prefix.address().toOctets(),
ip6Prefix.prefixLength())
.build();
final PiTableAction action = PiActionProfileGroupId.of(groupId);
// ---- END SOLUTION ----
return Utils.buildFlowRule(
deviceId, appId, tableId, match, action);
}
示例4
private PiTableAction decodeTableActionMsg(
P4RuntimeOuterClass.TableAction tableActionMsg, PiPipeconf pipeconf)
throws CodecException {
P4RuntimeOuterClass.TableAction.TypeCase typeCase = tableActionMsg.getTypeCase();
switch (typeCase) {
case ACTION:
P4RuntimeOuterClass.Action actionMsg = tableActionMsg.getAction();
return CODECS.action().decode(
actionMsg, null, pipeconf);
case ACTION_PROFILE_GROUP_ID:
return PiActionProfileGroupId.of(
tableActionMsg.getActionProfileGroupId());
case ACTION_PROFILE_MEMBER_ID:
return PiActionProfileMemberId.of(
tableActionMsg.getActionProfileMemberId());
default:
throw new CodecException(
format("Decoding of table action type %s not implemented",
typeCase.name()));
}
}
示例5
/**
* Tests the encoding of protocol-independent instructions.
*/
@Test
public void piInstructionEncodingTest() {
PiActionId actionId = PiActionId.of("set_egress_port");
PiActionParamId actionParamId = PiActionParamId.of("port");
PiActionParam actionParam = new PiActionParam(actionParamId, ImmutableByteSequence.copyFrom(10));
PiTableAction action = PiAction.builder().withId(actionId).withParameter(actionParam).build();
final PiInstruction actionInstruction = Instructions.piTableAction(action);
final ObjectNode actionInstructionJson =
instructionCodec.encode(actionInstruction, context);
assertThat(actionInstructionJson, matchesInstruction(actionInstruction));
PiTableAction actionGroupId = PiActionProfileGroupId.of(10);
final PiInstruction actionGroupIdInstruction = Instructions.piTableAction(actionGroupId);
final ObjectNode actionGroupIdInstructionJson =
instructionCodec.encode(actionGroupIdInstruction, context);
assertThat(actionGroupIdInstructionJson, matchesInstruction(actionGroupIdInstruction));
PiTableAction actionProfileMemberId = PiActionProfileMemberId.of(10);
final PiInstruction actionProfileMemberIdInstruction = Instructions.piTableAction(actionProfileMemberId);
final ObjectNode actionProfileMemberIdInstructionJson =
instructionCodec.encode(actionProfileMemberIdInstruction, context);
assertThat(actionProfileMemberIdInstructionJson, matchesInstruction(actionProfileMemberIdInstruction));
}
示例6
/**
* Sets up the "My Station" table for the given device using the
* myStationMac address found in the config.
* <p>
* This method will be called at component activation for each device
* (switch) known by ONOS, and every time a new device-added event is
* captured by the InternalDeviceListener defined below.
*
* @param deviceId the device ID
*/
private void setUpMyStationTable(DeviceId deviceId) {
log.info("Adding My Station rules to {}...", deviceId);
final MacAddress myStationMac = getMyStationMac(deviceId);
// HINT: in the p4 program, the My Station table matches on the
// *ethernet destination* and there is only one action called
// *NoAction*, which is used as an indication of "table hit" in the
// control block.
final String tableId = "IngressPipeImpl.my_station_table";
final PiCriterion match = PiCriterion.builder()
.matchExact(
PiMatchFieldId.of("hdr.ethernet.dst_addr"),
myStationMac.toBytes())
.build();
// Creates an action which do *NoAction* when hit.
final PiTableAction action = PiAction.builder()
.withId(PiActionId.of("NoAction"))
.build();
final FlowRule myStationRule = Utils.buildFlowRule(
deviceId, appId, tableId, match, action);
flowRuleService.applyFlowRules(myStationRule);
}
示例7
public static FlowRule buildFlowRule(DeviceId switchId, ApplicationId appId,
String tableId, PiCriterion piCriterion,
PiTableAction piAction) {
return DefaultFlowRule.builder()
.forDevice(switchId)
.forTable(PiTableId.of(tableId))
.fromApp(appId)
.withPriority(DEFAULT_FLOW_RULE_PRIORITY)
.makePermanent()
.withSelector(DefaultTrafficSelector.builder()
.matchPi(piCriterion).build())
.withTreatment(DefaultTrafficTreatment.builder()
.piTableAction(piAction).build())
.build();
}
示例8
/**
* Sets up the "My Station" table for the given device using the
* myStationMac address found in the config.
* <p>
* This method will be called at component activation for each device
* (switch) known by ONOS, and every time a new device-added event is
* captured by the InternalDeviceListener defined below.
*
* @param deviceId the device ID
*/
private void setUpMyStationTable(DeviceId deviceId) {
log.info("Adding My Station rules to {}...", deviceId);
final MacAddress myStationMac = getMyStationMac(deviceId);
// HINT: in our solution, the My Station table matches on the *ethernet
// destination* and there is only one action called *NoAction*, which is
// used as an indication of "table hit" in the control block.
// TODO EXERCISE 3
// Modify P4Runtime entity names to match content of P4Info file (look
// for the fully qualified name of tables, match fields, and actions.
// ---- START SOLUTION ----
final String tableId = "IngressPipeImpl.l2_my_station";
final PiCriterion match = PiCriterion.builder()
.matchExact(
PiMatchFieldId.of("hdr.ethernet.dst_addr"),
myStationMac.toBytes())
.build();
// Creates an action which do *NoAction* when hit.
final PiTableAction action = PiAction.builder()
.withId(PiActionId.of("NoAction"))
.build();
// ---- END SOLUTION ----
final FlowRule myStationRule = Utils.buildFlowRule(
deviceId, appId, tableId, match, action);
flowRuleService.applyFlowRules(myStationRule);
}
示例9
public static FlowRule buildFlowRule(DeviceId switchId, ApplicationId appId,
String tableId, PiCriterion piCriterion,
PiTableAction piAction) {
return DefaultFlowRule.builder()
.forDevice(switchId)
.forTable(PiTableId.of(tableId))
.fromApp(appId)
.withPriority(DEFAULT_FLOW_RULE_PRIORITY)
.makePermanent()
.withSelector(DefaultTrafficSelector.builder()
.matchPi(piCriterion).build())
.withTreatment(DefaultTrafficTreatment.builder()
.piTableAction(piAction).build())
.build();
}
示例10
/**
* Populate the My SID table from the network configuration for the
* specified device.
*
* @param deviceId the device Id
*/
private void setUpMySidTable(DeviceId deviceId) {
Ip6Address mySid = getMySid(deviceId);
log.info("Adding mySid rule on {} (sid {})...", deviceId, mySid);
// TODO EXERCISE 4
// Fill in the table ID for the SRv6 my segment identifier table
// ---- START SOLUTION ----
String tableId = "IngressPipeImpl.srv6_my_sid";
// ---- END SOLUTION ----
// TODO EXERCISE 4
// Modify the field and action id to match your P4Info
// ---- START SOLUTION ----
PiCriterion match = PiCriterion.builder()
.matchLpm(
PiMatchFieldId.of("hdr.ipv6.dst_addr"),
mySid.toOctets(), 128)
.build();
PiTableAction action = PiAction.builder()
.withId(PiActionId.of("IngressPipeImpl.srv6_end"))
.build();
// ---- END SOLUTION ----
FlowRule myStationRule = Utils.buildFlowRule(
deviceId, appId, tableId, match, action);
flowRuleService.applyFlowRules(myStationRule);
}
示例11
/**
* Sets up the "My Station" table for the given device using the
* myStationMac address found in the config.
* <p>
* This method will be called at component activation for each device
* (switch) known by ONOS, and every time a new device-added event is
* captured by the InternalDeviceListener defined below.
*
* @param deviceId the device ID
*/
private void setUpMyStationTable(DeviceId deviceId) {
log.info("Adding My Station rules to {}...", deviceId);
final MacAddress myStationMac = getMyStationMac(deviceId);
// HINT: in our solution, the My Station table matches on the *ethernet
// destination* and there is only one action called *NoAction*, which is
// used as an indication of "table hit" in the control block.
// TODO EXERCISE 3
// Modify P4Runtime entity names to match content of P4Info file (look
// for the fully qualified name of tables, match fields, and actions.
// ---- START SOLUTION ----
final String tableId = "MODIFY ME";
final PiCriterion match = PiCriterion.builder()
.matchExact(
PiMatchFieldId.of("MODIFY ME"),
myStationMac.toBytes())
.build();
// Creates an action which do *NoAction* when hit.
final PiTableAction action = PiAction.builder()
.withId(PiActionId.of("MODIFY ME"))
.build();
// ---- END SOLUTION ----
final FlowRule myStationRule = Utils.buildFlowRule(
deviceId, appId, tableId, match, action);
flowRuleService.applyFlowRules(myStationRule);
}
示例12
public static FlowRule buildFlowRule(DeviceId switchId, ApplicationId appId,
String tableId, PiCriterion piCriterion,
PiTableAction piAction) {
return DefaultFlowRule.builder()
.forDevice(switchId)
.forTable(PiTableId.of(tableId))
.fromApp(appId)
.withPriority(DEFAULT_FLOW_RULE_PRIORITY)
.makePermanent()
.withSelector(DefaultTrafficSelector.builder()
.matchPi(piCriterion).build())
.withTreatment(DefaultTrafficTreatment.builder()
.piTableAction(piAction).build())
.build();
}
示例13
/**
* Populate the My SID table from the network configuration for the
* specified device.
*
* @param deviceId the device Id
*/
private void setUpMySidTable(DeviceId deviceId) {
Ip6Address mySid = getMySid(deviceId);
log.info("Adding mySid rule on {} (sid {})...", deviceId, mySid);
// TODO EXERCISE 4
// Fill in the table ID for the SRv6 my segment identifier table
// ---- START SOLUTION ----
String tableId = "MODIFY ME";
// ---- END SOLUTION ----
// TODO EXERCISE 4
// Modify the field and action id to match your P4Info
// ---- START SOLUTION ----
PiCriterion match = PiCriterion.builder()
.matchLpm(
PiMatchFieldId.of("MODIFY ME"),
mySid.toOctets(), 128)
.build();
PiTableAction action = PiAction.builder()
.withId(PiActionId.of("MODIFY ME"))
.build();
// ---- END SOLUTION ----
FlowRule myStationRule = Utils.buildFlowRule(
deviceId, appId, tableId, match, action);
flowRuleService.applyFlowRules(myStationRule);
}
示例14
private P4RuntimeOuterClass.TableAction encodePiTableAction(
PiTableAction piTableAction, PiPipeconf pipeconf)
throws CodecException {
checkNotNull(piTableAction, "Cannot encode null PiTableAction");
final P4RuntimeOuterClass.TableAction.Builder tableActionMsgBuilder =
P4RuntimeOuterClass.TableAction.newBuilder();
switch (piTableAction.type()) {
case ACTION:
P4RuntimeOuterClass.Action theAction = CODECS.action()
.encode((PiAction) piTableAction, null, pipeconf);
tableActionMsgBuilder.setAction(theAction);
break;
case ACTION_PROFILE_GROUP_ID:
tableActionMsgBuilder.setActionProfileGroupId(
((PiActionProfileGroupId) piTableAction).id());
break;
case ACTION_PROFILE_MEMBER_ID:
tableActionMsgBuilder.setActionProfileMemberId(
((PiActionProfileMemberId) piTableAction).id());
break;
default:
throw new CodecException(
format("Building of table action type %s not implemented",
piTableAction.type()));
}
return tableActionMsgBuilder.build();
}
示例15
/**
* Builds a PI action out of the given treatment, optionally using the given
* interpreter.
*/
private static PiTableAction buildAction(TrafficTreatment treatment, PiPipelineInterpreter interpreter,
PiTableId tableId)
throws PiTranslationException {
PiTableAction piTableAction = null;
// If treatment has only one instruction of type PiInstruction, use that.
for (Instruction inst : treatment.allInstructions()) {
if (inst.type() == Instruction.Type.PROTOCOL_INDEPENDENT) {
if (treatment.allInstructions().size() == 1) {
piTableAction = ((PiInstruction) inst).action();
} else {
throw new PiTranslationException(format(
"Unable to translate treatment, found multiple instructions " +
"of which one is protocol-independent: %s", treatment));
}
}
}
if (piTableAction == null && interpreter != null) {
// No PiInstruction, use interpreter to build action.
try {
piTableAction = interpreter.mapTreatment(treatment, tableId);
} catch (PiPipelineInterpreter.PiInterpreterException e) {
throw new PiTranslationException(
"Interpreter was unable to translate treatment. " + e.getMessage());
}
}
return piTableAction;
}
示例16
private static PiTableAction typeCheckAction(PiTableAction piTableAction, PiTableModel table)
throws PiTranslationException {
if (piTableAction == null) {
// skip check if null
return null;
}
switch (piTableAction.type()) {
case ACTION:
return checkPiAction((PiAction) piTableAction, table);
case ACTION_PROFILE_GROUP_ID:
case ACTION_PROFILE_MEMBER_ID:
if (!table.tableType().equals(PiTableType.INDIRECT)) {
throw new PiTranslationException(format(
"action is indirect of type '%s', but table '%s' is of type '%s'",
piTableAction.type(), table.id(), table.tableType()));
}
if (piTableAction.type().equals(PiTableAction.Type.ACTION_PROFILE_GROUP_ID)
&& (table.actionProfile() == null || !table.actionProfile().hasSelector())) {
throw new PiTranslationException(format(
"action is of type '%s', but table '%s' does not" +
"implement an action profile with dynamic selection",
piTableAction.type(), table.id()));
}
return piTableAction;
default:
throw new PiTranslationException(format(
"Unknown table action type %s", piTableAction.type()));
}
}
示例17
private static PiTableAction checkPiAction(PiAction piAction, PiTableModel table)
throws PiTranslationException {
// Table supports this action?
PiActionModel actionModel = table.action(piAction.id()).orElseThrow(
() -> new PiTranslationException(format("Not such action '%s' for table '%s'",
piAction.id(), table.id())));
// Is the number of runtime parameters correct?
if (actionModel.params().size() != piAction.parameters().size()) {
throw new PiTranslationException(format(
"Wrong number of runtime parameters for action '%s', expected %d but found %d",
actionModel.id(), actionModel.params().size(), piAction.parameters().size()));
}
// Forge a new action instance with well-sized parameters.
// The same comment as in typeCheckFieldMatch() about duplicating field match instances applies here.
PiAction.Builder newActionBuilder = PiAction.builder().withId(piAction.id());
for (PiActionParam param : piAction.parameters()) {
PiActionParamModel paramModel = actionModel.param(param.id())
.orElseThrow(() -> new PiTranslationException(format(
"Not such parameter '%s' for action '%s'", param.id(), actionModel)));
try {
newActionBuilder.withParameter(new PiActionParam(param.id(),
param.value().fit(paramModel.bitWidth())));
} catch (ByteSequenceTrimException e) {
throw new PiTranslationException(format(
"Size mismatch for parameter '%s' of action '%s': %s",
param.id(), piAction.id(), e.getMessage()));
}
}
return newActionBuilder.build();
}
示例18
private static GroupBucket selectOutputBucket(int portNum) {
ImmutableByteSequence paramVal = copyFrom(portNum);
PiActionParam param = new PiActionParam(PORT, paramVal);
PiTableAction action = PiAction.builder()
.withId(INGRESS_WCMP_CONTROL_SET_EGRESS_PORT)
.withParameter(param).build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.add(Instructions.piTableAction(action))
.build();
return DefaultGroupBucket.createSelectGroupBucket(treatment);
}
示例19
/**
* Tests the decoding of protocol-independent instructions.
*/
@Test
public void piInstructionDecodingTest() throws IOException {
Instruction actionInstruction = getInstruction("PiActionInstruction.json");
Assert.assertThat(actionInstruction.type(), is(Instruction.Type.PROTOCOL_INDEPENDENT));
PiTableAction action = ((PiInstruction) actionInstruction).action();
Assert.assertThat(action.type(), is(PiTableAction.Type.ACTION));
Assert.assertThat(((PiAction) action).id().id(), is("set_egress_port"));
Assert.assertThat(((PiAction) action).parameters().size(), is(1));
Collection<PiActionParam> actionParams = ((PiAction) action).parameters();
PiActionParam actionParam = actionParams.iterator().next();
Assert.assertThat(actionParam.id().id(), is("port"));
Assert.assertThat(actionParam.value(), is(copyFrom((byte) 0x1)));
Instruction actionGroupIdInstruction = getInstruction("PiActionProfileGroupIdInstruction.json");
Assert.assertThat(actionInstruction.type(), is(Instruction.Type.PROTOCOL_INDEPENDENT));
PiTableAction actionGroupId = ((PiInstruction) actionGroupIdInstruction).action();
Assert.assertThat(actionGroupId.type(), is(PiTableAction.Type.ACTION_PROFILE_GROUP_ID));
Assert.assertThat(((PiActionProfileGroupId) actionGroupId).id(), is(100));
Instruction actionMemberIdInstruction = getInstruction("PiActionProfileMemberIdInstruction.json");
Assert.assertThat(actionInstruction.type(), is(Instruction.Type.PROTOCOL_INDEPENDENT));
PiTableAction actionMemberId = ((PiInstruction) actionMemberIdInstruction).action();
Assert.assertThat(actionMemberId.type(), is(PiTableAction.Type.ACTION_PROFILE_MEMBER_ID));
Assert.assertThat(((PiActionProfileMemberId) actionMemberId).id(), is(100));
}
示例20
/**
* Returns a PI table entry equivalent to the given flow rule, for the given
* pipeconf and device.
*
* @param rule flow rule
* @param pipeconf pipeconf
* @param device device
* @return PI table entry
* @throws PiTranslationException if the flow rule cannot be translated
*/
static PiTableEntry translate(FlowRule rule, PiPipeconf pipeconf, Device device)
throws PiTranslationException {
PiPipelineModel pipelineModel = pipeconf.pipelineModel();
// Retrieve interpreter, if any.
final PiPipelineInterpreter interpreter = getInterpreterOrNull(device, pipeconf);
// Get table model.
final PiTableId piTableId = translateTableId(rule.table(), interpreter);
final PiTableModel tableModel = getTableModel(piTableId, pipelineModel);
// Translate selector.
final PiMatchKey piMatchKey;
final boolean needPriority;
if (rule.selector().criteria().isEmpty()) {
piMatchKey = PiMatchKey.EMPTY;
needPriority = false;
} else {
final Collection<PiFieldMatch> fieldMatches = translateFieldMatches(
interpreter, rule.selector(), tableModel);
piMatchKey = PiMatchKey.builder()
.addFieldMatches(fieldMatches)
.build();
// FIXME: P4Runtime limit
// Need to ignore priority if no TCAM lookup match field
needPriority = tableModel.matchFields().stream()
.anyMatch(match -> match.matchType() == PiMatchType.TERNARY ||
match.matchType() == PiMatchType.RANGE);
}
// Translate treatment.
final PiTableAction piTableAction = translateTreatment(rule.treatment(), interpreter, piTableId, pipelineModel);
// Build PI entry.
final PiTableEntry.Builder tableEntryBuilder = PiTableEntry.builder();
tableEntryBuilder
.forTable(piTableId)
.withMatchKey(piMatchKey);
if (piTableAction != null) {
tableEntryBuilder.withAction(piTableAction);
}
if (needPriority) {
// FIXME: move priority check to P4Runtime driver.
final int newPriority;
if (rule.priority() > MAX_PI_PRIORITY) {
log.warn("Flow rule priority too big, setting translated priority to max value {}: {}",
MAX_PI_PRIORITY, rule);
newPriority = MAX_PI_PRIORITY;
} else {
newPriority = MIN_PI_PRIORITY + rule.priority();
}
tableEntryBuilder.withPriority(newPriority);
}
if (!rule.isPermanent()) {
if (tableModel.supportsAging()) {
tableEntryBuilder.withTimeout((double) rule.timeout());
} else {
log.debug("Flow rule is temporary, but table '{}' doesn't support " +
"aging, translating to permanent.", tableModel.id());
}
}
return tableEntryBuilder.build();
}
示例21
/**
* Returns a PI action equivalent to the given treatment, optionally using
* the given interpreter. This method also checks that the produced PI table
* action is suitable for the given table ID and pipeline model. If
* suitable, the returned action instance will have parameters well-sized,
* according to the table model.
*
* @param treatment traffic treatment
* @param interpreter interpreter
* @param tableId PI table ID
* @param pipelineModel pipeline model
* @return PI table action
* @throws PiTranslationException if the treatment cannot be translated or
* if the PI action is not suitable for the
* given pipeline model
*/
static PiTableAction translateTreatment(TrafficTreatment treatment, PiPipelineInterpreter interpreter,
PiTableId tableId, PiPipelineModel pipelineModel)
throws PiTranslationException {
PiTableModel tableModel = getTableModel(tableId, pipelineModel);
return typeCheckAction(buildAction(treatment, interpreter, tableId), tableModel);
}
示例22
/**
* Creates a new instruction with the given protocol-independent table action.
*
* @param tableAction a protocol-independent action
*/
PiInstruction(PiTableAction tableAction) {
this.tableAction = tableAction;
}
示例23
/**
* Returns the protocol-independent table action defined by this instruction.
*
* @return an action
*/
public PiTableAction action() {
return tableAction;
}