ONOS-4410 Implemented PacketProgrammable and Pipeliner behaviors in the
BMv2 driver
Also other minor fixes / refactorings
Change-Id: I2205890b76471e8e8490beccd6b36e5358f8d407
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/translators/Bmv2SimpleTranslatorConfig.java b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/translators/Bmv2SimpleTranslatorConfig.java
new file mode 100644
index 0000000..565c1e4
--- /dev/null
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/translators/Bmv2SimpleTranslatorConfig.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.bmv2.translators;
+
+import com.eclipsesource.json.Json;
+import com.eclipsesource.json.JsonObject;
+import com.google.common.annotations.Beta;
+import com.google.common.collect.Maps;
+import org.onlab.util.ImmutableByteSequence;
+import org.onosproject.bmv2.api.model.Bmv2Model;
+import org.onosproject.bmv2.api.runtime.Bmv2Action;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Map;
+
+/**
+ * Implementation of a Bmv2 flow rule translator configuration for the
+ * simple.p4 model.
+ */
+@Beta
+public class Bmv2SimpleTranslatorConfig implements Bmv2FlowRuleTranslator.TranslatorConfig {
+
+ private static final String JSON_CONFIG_PATH = "/simple.json";
+ private final Map<String, Criterion.Type> fieldMap = Maps.newHashMap();
+ private final Bmv2Model model;
+
+ /**
+ * Creates a new simple pipeline translator configuration.
+ */
+ public Bmv2SimpleTranslatorConfig() {
+
+ this.model = getModel();
+
+ // populate fieldMap
+ fieldMap.put("standard_metadata.ingress_port", Criterion.Type.IN_PORT);
+ fieldMap.put("ethernet.dstAddr", Criterion.Type.ETH_DST);
+ fieldMap.put("ethernet.srcAddr", Criterion.Type.ETH_SRC);
+ fieldMap.put("ethernet.etherType", Criterion.Type.ETH_TYPE);
+ }
+
+ private static Bmv2Action buildDropAction() {
+ return Bmv2Action.builder()
+ .withName("_drop")
+ .build();
+ }
+
+ private static Bmv2Action buildPushToCpAction() {
+ return Bmv2Action.builder()
+ .withName("send_to_cpu")
+ .build();
+ }
+
+ private static Bmv2Action buildFwdAction(Instructions.OutputInstruction inst)
+ throws Bmv2FlowRuleTranslatorException {
+
+ Bmv2Action.Builder actionBuilder = Bmv2Action.builder();
+
+ actionBuilder.withName("fwd");
+
+ if (inst.port().isLogical()) {
+ if (inst.port() == PortNumber.CONTROLLER) {
+ return buildPushToCpAction();
+ } else {
+ throw new Bmv2FlowRuleTranslatorException(
+ "Output logic port number not supported: " + inst);
+ }
+ }
+
+ actionBuilder.addParameter(
+ ImmutableByteSequence.copyFrom((short) inst.port().toLong()));
+
+ return actionBuilder.build();
+ }
+
+ private static Bmv2Model getModel() {
+ InputStream inputStream = Bmv2SimpleTranslatorConfig.class
+ .getResourceAsStream(JSON_CONFIG_PATH);
+ InputStreamReader reader = new InputStreamReader(inputStream);
+ BufferedReader bufReader = new BufferedReader(reader);
+ JsonObject json = null;
+ try {
+ json = Json.parse(bufReader).asObject();
+ } catch (IOException e) {
+ throw new RuntimeException("Unable to parse JSON file: " + e.getMessage());
+ }
+
+ return Bmv2Model.parse(json);
+ }
+
+ @Override
+ public Bmv2Model model() {
+ return this.model;
+ }
+
+ @Override
+ public Map<String, Criterion.Type> fieldToCriterionTypeMap() {
+ return fieldMap;
+ }
+
+ @Override
+ public Bmv2Action buildAction(TrafficTreatment treatment)
+ throws Bmv2FlowRuleTranslatorException {
+
+
+ if (treatment.allInstructions().size() == 0) {
+ // no instructions means drop
+ return buildDropAction();
+ } else if (treatment.allInstructions().size() > 1) {
+ // otherwise, we understand treatments with only 1 instruction
+ throw new Bmv2FlowRuleTranslatorException(
+ "Treatment not supported, more than 1 instructions found: "
+ + treatment.toString());
+ }
+
+ Instruction instruction = treatment.allInstructions().get(0);
+
+ switch (instruction.type()) {
+ case OUTPUT:
+ return buildFwdAction((Instructions.OutputInstruction) instruction);
+ case NOACTION:
+ return buildDropAction();
+ default:
+ throw new Bmv2FlowRuleTranslatorException(
+ "Instruction type not supported: "
+ + instruction.type().name());
+ }
+ }
+}