@Test public void testTranslate() throws Exception { DeviceId deviceId = DeviceId.NONE; ApplicationId appId = new DefaultApplicationId(1, "test"); int tableId = 0; MacAddress ethDstMac = MacAddress.valueOf(random.nextLong()); MacAddress ethSrcMac = MacAddress.valueOf(random.nextLong()); short ethType = (short) (0x0000FFFF & random.nextInt()); short outPort = (short) random.nextInt(65); short inPort = (short) random.nextInt(65); int timeout = random.nextInt(100); int priority = random.nextInt(100); TrafficSelector matchInPort1 = DefaultTrafficSelector .builder() .matchInPort(PortNumber.portNumber(inPort)) .matchEthDst(ethDstMac) .matchEthSrc(ethSrcMac) .matchEthType(ethType) .build(); TrafficTreatment outPort2 = DefaultTrafficTreatment .builder() .setOutput(PortNumber.portNumber(outPort)) .build(); FlowRule rule1 = DefaultFlowRule.builder() .forDevice(deviceId) .forTable(tableId) .fromApp(appId) .withSelector(matchInPort1) .withTreatment(outPort2) .makeTemporary(timeout) .withPriority(priority) .build(); FlowRule rule2 = DefaultFlowRule.builder() .forDevice(deviceId) .forTable(tableId) .fromApp(appId) .withSelector(matchInPort1) .withTreatment(outPort2) .makeTemporary(timeout) .withPriority(priority) .build(); Bmv2TableEntry entry1 = translator.translate(rule1, context); Bmv2TableEntry entry2 = translator.translate(rule1, context); new EqualsTester() .addEqualityGroup(rule1, rule2) .addEqualityGroup(entry1, entry2) .testEquals(); int numMatchParams = configuration.table(TABLE0).keys().size(); Bmv2TernaryMatchParam inPortParam = (Bmv2TernaryMatchParam) entry1.matchKey().matchParams().get(0); Bmv2TernaryMatchParam ethDstParam = (Bmv2TernaryMatchParam) entry1.matchKey().matchParams().get(1); Bmv2TernaryMatchParam ethSrcParam = (Bmv2TernaryMatchParam) entry1.matchKey().matchParams().get(2); Bmv2TernaryMatchParam ethTypeParam = (Bmv2TernaryMatchParam) entry1.matchKey().matchParams().get(3); double expectedTimeout = (double) (configuration.table(TABLE0).hasTimeouts() ? rule1.timeout() : -1); assertThat("Incorrect number of match parameters", entry1.matchKey().matchParams().size(), is(equalTo(numMatchParams))); assertThat("Incorrect inPort match param value", inPortParam.value().asReadOnlyBuffer().getShort(), is(equalTo(inPort))); assertThat("Incorrect ethDestMac match param value", ethDstParam.value().asArray(), is(equalTo(ethDstMac.toBytes()))); assertThat("Incorrect ethSrcMac match param value", ethSrcParam.value().asArray(), is(equalTo(ethSrcMac.toBytes()))); assertThat("Incorrect ethType match param value", ethTypeParam.value().asReadOnlyBuffer().getShort(), is(equalTo(ethType))); assertThat("Incorrect priority value", entry1.priority(), is(equalTo(Integer.MAX_VALUE - rule1.priority()))); assertThat("Incorrect timeout value", entry1.timeout(), is(equalTo(expectedTimeout))); }
@Override public Bmv2TableEntry translate(FlowRule rule, Bmv2DeviceContext context) throws Bmv2FlowRuleTranslatorException { Bmv2Configuration configuration = context.configuration(); Bmv2Interpreter interpreter = context.interpreter(); int tableId = rule.tableId(); String tableName = interpreter.tableIdMap().get(tableId); Bmv2TableModel table = (tableName == null) ? configuration.table(tableId) : configuration.table(tableName); if (table == null) { throw new Bmv2FlowRuleTranslatorException("Unknown table ID: " + tableId); } Bmv2MatchKey bmv2MatchKey = buildMatchKey(interpreter, rule.selector(), table); TrafficTreatment treatment = rule.treatment(); Bmv2Action bmv2Action = null; for (Instruction inst : treatment.allInstructions()) { if (inst.type() == Instruction.Type.EXTENSION) { if (treatment.allInstructions().size() == 1) { bmv2Action = getActionFromExtension((ExtensionInstructionWrapper) inst); } else { throw new Bmv2FlowRuleTranslatorException("Unable to translate traffic treatment, found multiple " + "instructions of which one is an extension: " + treatment.toString()); } } } if (bmv2Action == null) { try { bmv2Action = interpreter.mapTreatment(treatment, configuration); } catch (Bmv2InterpreterException e) { throw new Bmv2FlowRuleTranslatorException("Unable to translate treatment. " + e.toString()); } } if (bmv2Action == null) { throw new Bmv2FlowRuleTranslatorException("Unable to translate treatment"); } Bmv2ActionModel actionModel = configuration.action(bmv2Action.name()); if (actionModel == null) { throw new Bmv2FlowRuleTranslatorException("Unknown action " + bmv2Action.name()); } if (!table.actions().contains(actionModel)) { throw new Bmv2FlowRuleTranslatorException("Action " + bmv2Action.name() + " is not defined for table " + tableName); } if (actionModel.runtimeDatas().size() != bmv2Action.parameters().size()) { throw new Bmv2FlowRuleTranslatorException("Wrong number of parameters for action " + actionModel.name() + ", expected " + actionModel.runtimeDatas().size() + ", but found " + bmv2Action.parameters().size()); } for (int i = 0; i < actionModel.runtimeDatas().size(); i++) { Bmv2RuntimeDataModel data = actionModel.runtimeDatas().get(i); ImmutableByteSequence param = bmv2Action.parameters().get(i); if (param.size() != roundToBytes(data.bitWidth())) { throw new Bmv2FlowRuleTranslatorException("Wrong byte-width for parameter " + data.name() + " of action " + actionModel.name() + ", expected " + roundToBytes(data.bitWidth()) + " bytes, but found " + param.size()); } } Bmv2TableEntry.Builder tableEntryBuilder = Bmv2TableEntry.builder(); int newPriority = Integer.MAX_VALUE - rule.priority(); tableEntryBuilder .withTableName(table.name()) .withPriority(newPriority) .withMatchKey(bmv2MatchKey) .withAction(bmv2Action); if (!rule.isPermanent()) { if (table.hasTimeouts()) { tableEntryBuilder.withTimeout((double) rule.timeout()); } else { log.warn("Flow rule is temporary but table {} doesn't support timeouts, translating to permanent", table.name()); } } return tableEntryBuilder.build(); }
Bmv2FlowRuleTranslatorImpl implements Bmv2FlowRuleTranslator { @Override public Bmv2TableEntry translate(FlowRule rule, Bmv2DeviceContext context) throws Bmv2FlowRuleTranslatorException { Bmv2Configuration configuration = context.configuration(); Bmv2Interpreter interpreter = context.interpreter(); int tableId = rule.tableId(); String tableName = interpreter.tableIdMap().get(tableId); Bmv2TableModel table = (tableName == null) ? configuration.table(tableId) : configuration.table(tableName); if (table == null) { throw new Bmv2FlowRuleTranslatorException("Unknown table ID: " + tableId); } Bmv2MatchKey bmv2MatchKey = buildMatchKey(interpreter, rule.selector(), table); TrafficTreatment treatment = rule.treatment(); Bmv2Action bmv2Action = null; for (Instruction inst : treatment.allInstructions()) { if (inst.type() == Instruction.Type.EXTENSION) { if (treatment.allInstructions().size() == 1) { bmv2Action = getActionFromExtension((ExtensionInstructionWrapper) inst); } else { throw new Bmv2FlowRuleTranslatorException("Unable to translate traffic treatment, found multiple " + "instructions of which one is an extension: " + treatment.toString()); } } } if (bmv2Action == null) { try { bmv2Action = interpreter.mapTreatment(treatment, configuration); } catch (Bmv2InterpreterException e) { throw new Bmv2FlowRuleTranslatorException("Unable to translate treatment. " + e.toString()); } } if (bmv2Action == null) { throw new Bmv2FlowRuleTranslatorException("Unable to translate treatment"); } Bmv2ActionModel actionModel = configuration.action(bmv2Action.name()); if (actionModel == null) { throw new Bmv2FlowRuleTranslatorException("Unknown action " + bmv2Action.name()); } if (!table.actions().contains(actionModel)) { throw new Bmv2FlowRuleTranslatorException("Action " + bmv2Action.name() + " is not defined for table " + tableName); } if (actionModel.runtimeDatas().size() != bmv2Action.parameters().size()) { throw new Bmv2FlowRuleTranslatorException("Wrong number of parameters for action " + actionModel.name() + ", expected " + actionModel.runtimeDatas().size() + ", but found " + bmv2Action.parameters().size()); } for (int i = 0; i < actionModel.runtimeDatas().size(); i++) { Bmv2RuntimeDataModel data = actionModel.runtimeDatas().get(i); ImmutableByteSequence param = bmv2Action.parameters().get(i); if (param.size() != roundToBytes(data.bitWidth())) { throw new Bmv2FlowRuleTranslatorException("Wrong byte-width for parameter " + data.name() + " of action " + actionModel.name() + ", expected " + roundToBytes(data.bitWidth()) + " bytes, but found " + param.size()); } } Bmv2TableEntry.Builder tableEntryBuilder = Bmv2TableEntry.builder(); int newPriority = Integer.MAX_VALUE - rule.priority(); tableEntryBuilder .withTableName(table.name()) .withPriority(newPriority) .withMatchKey(bmv2MatchKey) .withAction(bmv2Action); if (!rule.isPermanent()) { if (table.hasTimeouts()) { tableEntryBuilder.withTimeout((double) rule.timeout()); } else { log.warn("Flow rule is temporary but table {} doesn't support timeouts, translating to permanent", table.name()); } } return tableEntryBuilder.build(); } }
Bmv2FlowRuleTranslatorImpl implements Bmv2FlowRuleTranslator { @Override public Bmv2TableEntry translate(FlowRule rule, Bmv2DeviceContext context) throws Bmv2FlowRuleTranslatorException { Bmv2Configuration configuration = context.configuration(); Bmv2Interpreter interpreter = context.interpreter(); int tableId = rule.tableId(); String tableName = interpreter.tableIdMap().get(tableId); Bmv2TableModel table = (tableName == null) ? configuration.table(tableId) : configuration.table(tableName); if (table == null) { throw new Bmv2FlowRuleTranslatorException("Unknown table ID: " + tableId); } Bmv2MatchKey bmv2MatchKey = buildMatchKey(interpreter, rule.selector(), table); TrafficTreatment treatment = rule.treatment(); Bmv2Action bmv2Action = null; for (Instruction inst : treatment.allInstructions()) { if (inst.type() == Instruction.Type.EXTENSION) { if (treatment.allInstructions().size() == 1) { bmv2Action = getActionFromExtension((ExtensionInstructionWrapper) inst); } else { throw new Bmv2FlowRuleTranslatorException("Unable to translate traffic treatment, found multiple " + "instructions of which one is an extension: " + treatment.toString()); } } } if (bmv2Action == null) { try { bmv2Action = interpreter.mapTreatment(treatment, configuration); } catch (Bmv2InterpreterException e) { throw new Bmv2FlowRuleTranslatorException("Unable to translate treatment. " + e.toString()); } } if (bmv2Action == null) { throw new Bmv2FlowRuleTranslatorException("Unable to translate treatment"); } Bmv2ActionModel actionModel = configuration.action(bmv2Action.name()); if (actionModel == null) { throw new Bmv2FlowRuleTranslatorException("Unknown action " + bmv2Action.name()); } if (!table.actions().contains(actionModel)) { throw new Bmv2FlowRuleTranslatorException("Action " + bmv2Action.name() + " is not defined for table " + tableName); } if (actionModel.runtimeDatas().size() != bmv2Action.parameters().size()) { throw new Bmv2FlowRuleTranslatorException("Wrong number of parameters for action " + actionModel.name() + ", expected " + actionModel.runtimeDatas().size() + ", but found " + bmv2Action.parameters().size()); } for (int i = 0; i < actionModel.runtimeDatas().size(); i++) { Bmv2RuntimeDataModel data = actionModel.runtimeDatas().get(i); ImmutableByteSequence param = bmv2Action.parameters().get(i); if (param.size() != roundToBytes(data.bitWidth())) { throw new Bmv2FlowRuleTranslatorException("Wrong byte-width for parameter " + data.name() + " of action " + actionModel.name() + ", expected " + roundToBytes(data.bitWidth()) + " bytes, but found " + param.size()); } } Bmv2TableEntry.Builder tableEntryBuilder = Bmv2TableEntry.builder(); int newPriority = Integer.MAX_VALUE - rule.priority(); tableEntryBuilder .withTableName(table.name()) .withPriority(newPriority) .withMatchKey(bmv2MatchKey) .withAction(bmv2Action); if (!rule.isPermanent()) { if (table.hasTimeouts()) { tableEntryBuilder.withTimeout((double) rule.timeout()); } else { log.warn("Flow rule is temporary but table {} doesn't support timeouts, translating to permanent", table.name()); } } return tableEntryBuilder.build(); }  }
Bmv2FlowRuleTranslatorImpl implements Bmv2FlowRuleTranslator { @Override public Bmv2TableEntry translate(FlowRule rule, Bmv2DeviceContext context) throws Bmv2FlowRuleTranslatorException { Bmv2Configuration configuration = context.configuration(); Bmv2Interpreter interpreter = context.interpreter(); int tableId = rule.tableId(); String tableName = interpreter.tableIdMap().get(tableId); Bmv2TableModel table = (tableName == null) ? configuration.table(tableId) : configuration.table(tableName); if (table == null) { throw new Bmv2FlowRuleTranslatorException("Unknown table ID: " + tableId); } Bmv2MatchKey bmv2MatchKey = buildMatchKey(interpreter, rule.selector(), table); TrafficTreatment treatment = rule.treatment(); Bmv2Action bmv2Action = null; for (Instruction inst : treatment.allInstructions()) { if (inst.type() == Instruction.Type.EXTENSION) { if (treatment.allInstructions().size() == 1) { bmv2Action = getActionFromExtension((ExtensionInstructionWrapper) inst); } else { throw new Bmv2FlowRuleTranslatorException("Unable to translate traffic treatment, found multiple " + "instructions of which one is an extension: " + treatment.toString()); } } } if (bmv2Action == null) { try { bmv2Action = interpreter.mapTreatment(treatment, configuration); } catch (Bmv2InterpreterException e) { throw new Bmv2FlowRuleTranslatorException("Unable to translate treatment. " + e.toString()); } } if (bmv2Action == null) { throw new Bmv2FlowRuleTranslatorException("Unable to translate treatment"); } Bmv2ActionModel actionModel = configuration.action(bmv2Action.name()); if (actionModel == null) { throw new Bmv2FlowRuleTranslatorException("Unknown action " + bmv2Action.name()); } if (!table.actions().contains(actionModel)) { throw new Bmv2FlowRuleTranslatorException("Action " + bmv2Action.name() + " is not defined for table " + tableName); } if (actionModel.runtimeDatas().size() != bmv2Action.parameters().size()) { throw new Bmv2FlowRuleTranslatorException("Wrong number of parameters for action " + actionModel.name() + ", expected " + actionModel.runtimeDatas().size() + ", but found " + bmv2Action.parameters().size()); } for (int i = 0; i < actionModel.runtimeDatas().size(); i++) { Bmv2RuntimeDataModel data = actionModel.runtimeDatas().get(i); ImmutableByteSequence param = bmv2Action.parameters().get(i); if (param.size() != roundToBytes(data.bitWidth())) { throw new Bmv2FlowRuleTranslatorException("Wrong byte-width for parameter " + data.name() + " of action " + actionModel.name() + ", expected " + roundToBytes(data.bitWidth()) + " bytes, but found " + param.size()); } } Bmv2TableEntry.Builder tableEntryBuilder = Bmv2TableEntry.builder(); int newPriority = Integer.MAX_VALUE - rule.priority(); tableEntryBuilder .withTableName(table.name()) .withPriority(newPriority) .withMatchKey(bmv2MatchKey) .withAction(bmv2Action); if (!rule.isPermanent()) { if (table.hasTimeouts()) { tableEntryBuilder.withTimeout((double) rule.timeout()); } else { log.warn("Flow rule is temporary but table {} doesn't support timeouts, translating to permanent", table.name()); } } return tableEntryBuilder.build(); }  @Override Bmv2TableEntry translate(FlowRule rule, Bmv2DeviceContext context); }
Bmv2FlowRuleTranslatorImpl implements Bmv2FlowRuleTranslator { @Override public Bmv2TableEntry translate(FlowRule rule, Bmv2DeviceContext context) throws Bmv2FlowRuleTranslatorException { Bmv2Configuration configuration = context.configuration(); Bmv2Interpreter interpreter = context.interpreter(); int tableId = rule.tableId(); String tableName = interpreter.tableIdMap().get(tableId); Bmv2TableModel table = (tableName == null) ? configuration.table(tableId) : configuration.table(tableName); if (table == null) { throw new Bmv2FlowRuleTranslatorException("Unknown table ID: " + tableId); } Bmv2MatchKey bmv2MatchKey = buildMatchKey(interpreter, rule.selector(), table); TrafficTreatment treatment = rule.treatment(); Bmv2Action bmv2Action = null; for (Instruction inst : treatment.allInstructions()) { if (inst.type() == Instruction.Type.EXTENSION) { if (treatment.allInstructions().size() == 1) { bmv2Action = getActionFromExtension((ExtensionInstructionWrapper) inst); } else { throw new Bmv2FlowRuleTranslatorException("Unable to translate traffic treatment, found multiple " + "instructions of which one is an extension: " + treatment.toString()); } } } if (bmv2Action == null) { try { bmv2Action = interpreter.mapTreatment(treatment, configuration); } catch (Bmv2InterpreterException e) { throw new Bmv2FlowRuleTranslatorException("Unable to translate treatment. " + e.toString()); } } if (bmv2Action == null) { throw new Bmv2FlowRuleTranslatorException("Unable to translate treatment"); } Bmv2ActionModel actionModel = configuration.action(bmv2Action.name()); if (actionModel == null) { throw new Bmv2FlowRuleTranslatorException("Unknown action " + bmv2Action.name()); } if (!table.actions().contains(actionModel)) { throw new Bmv2FlowRuleTranslatorException("Action " + bmv2Action.name() + " is not defined for table " + tableName); } if (actionModel.runtimeDatas().size() != bmv2Action.parameters().size()) { throw new Bmv2FlowRuleTranslatorException("Wrong number of parameters for action " + actionModel.name() + ", expected " + actionModel.runtimeDatas().size() + ", but found " + bmv2Action.parameters().size()); } for (int i = 0; i < actionModel.runtimeDatas().size(); i++) { Bmv2RuntimeDataModel data = actionModel.runtimeDatas().get(i); ImmutableByteSequence param = bmv2Action.parameters().get(i); if (param.size() != roundToBytes(data.bitWidth())) { throw new Bmv2FlowRuleTranslatorException("Wrong byte-width for parameter " + data.name() + " of action " + actionModel.name() + ", expected " + roundToBytes(data.bitWidth()) + " bytes, but found " + param.size()); } } Bmv2TableEntry.Builder tableEntryBuilder = Bmv2TableEntry.builder(); int newPriority = Integer.MAX_VALUE - rule.priority(); tableEntryBuilder .withTableName(table.name()) .withPriority(newPriority) .withMatchKey(bmv2MatchKey) .withAction(bmv2Action); if (!rule.isPermanent()) { if (table.hasTimeouts()) { tableEntryBuilder.withTimeout((double) rule.timeout()); } else { log.warn("Flow rule is temporary but table {} doesn't support timeouts, translating to permanent", table.name()); } } return tableEntryBuilder.build(); }  @Override Bmv2TableEntry translate(FlowRule rule, Bmv2DeviceContext context);  }