[AETHER-239] Add RAW_DEVICE_CONFIG extension

Change-Id: I0acc1039800c7e69b87e3195f4f7ee732df241c0
diff --git a/core/api/src/main/java/org/onosproject/net/pi/model/PiPipeconf.java b/core/api/src/main/java/org/onosproject/net/pi/model/PiPipeconf.java
index 098bef7..9ebd70f 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/model/PiPipeconf.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/model/PiPipeconf.java
@@ -125,6 +125,11 @@
         // TODO: consider a better way to get the CPU port in the interpreter
         // (see FabricInterpreter.java mapLogicalPortNumber). Perhaps using
         // pipeconf annotations?
-        CPU_PORT_TXT
+        CPU_PORT_TXT,
+
+        /**
+         * Raw device config.
+         */
+        RAW_DEVICE_CONFIG
     }
 }
diff --git a/drivers/barefoot/src/main/java/org/onosproject/drivers/barefoot/TofinoPipelineProgrammable.java b/drivers/barefoot/src/main/java/org/onosproject/drivers/barefoot/TofinoPipelineProgrammable.java
index 114b2af..7b50377 100644
--- a/drivers/barefoot/src/main/java/org/onosproject/drivers/barefoot/TofinoPipelineProgrammable.java
+++ b/drivers/barefoot/src/main/java/org/onosproject/drivers/barefoot/TofinoPipelineProgrammable.java
@@ -31,6 +31,7 @@
 import java.util.List;
 import java.util.Optional;
 
+import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.RAW_DEVICE_CONFIG;
 import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.TOFINO_BIN;
 import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.TOFINO_CONTEXT_JSON;
 
@@ -48,14 +49,18 @@
 
     @Override
     public ByteBuffer createDeviceDataBuffer(PiPipeconf pipeconf) {
-
         List<ByteBuffer> buffers = Lists.newLinkedList();
-        try {
-            buffers.add(nameBuffer(pipeconf));
-            buffers.add(extensionBuffer(pipeconf, TOFINO_BIN));
-            buffers.add(extensionBuffer(pipeconf, TOFINO_CONTEXT_JSON));
-        } catch (ExtensionException e) {
-            return null;
+
+        if (pipeconf.extension(RAW_DEVICE_CONFIG).isPresent()) {
+            buffers.add(rawDeviceConfig(pipeconf));
+        } else {
+            try {
+                buffers.add(nameBuffer(pipeconf));
+                buffers.add(extensionBuffer(pipeconf, TOFINO_BIN));
+                buffers.add(extensionBuffer(pipeconf, TOFINO_CONTEXT_JSON));
+            } catch (ExtensionException e) {
+                return null;
+            }
         }
 
         // Concatenate buffers (flip so they can be read).
@@ -95,6 +100,19 @@
         }
     }
 
+    private ByteBuffer rawDeviceConfig(PiPipeconf pipeconf) {
+        try {
+            byte[] bytes = IOUtils.toByteArray(pipeconf.extension(RAW_DEVICE_CONFIG).get());
+            return ByteBuffer.allocate(bytes.length)
+                    .order(ByteOrder.LITTLE_ENDIAN)
+                    .put(bytes);
+        } catch (IOException ex) {
+            log.warn("Unable to read raw device config from pipeconf {}: {}",
+                     pipeconf.id(), ex.getMessage());
+            throw new ExtensionException();
+        }
+    }
+
     private static class ExtensionException extends IllegalArgumentException {
     }
 }