Java tutorial
/* * Copyright 2017-present Open Networking Foundation * * 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.barefoot; import com.google.common.collect.Lists; import org.apache.commons.io.IOUtils; import org.onosproject.drivers.p4runtime.AbstractP4RuntimePipelineProgrammable; import org.onosproject.net.behaviour.PiPipelineProgrammable; import org.onosproject.net.pi.model.PiPipeconf; import org.onosproject.net.pi.model.PiPipeconf.ExtensionType; import java.io.IOException; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Optional; import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.TOFINO_BIN; import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.TOFINO_CONTEXT_JSON; /** * Implementation of the PiPipelineProgrammable behaviour for a Tofino-based switch. */ public class TofinoPipelineProgrammable extends AbstractP4RuntimePipelineProgrammable implements PiPipelineProgrammable { @Override public Optional<PiPipeconf> getDefaultPipeconf() { return Optional.empty(); } @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; } // Concatenate buffers (flip so they can be read). int len = buffers.stream().mapToInt(Buffer::limit).sum(); ByteBuffer deviceData = ByteBuffer.allocate(len); buffers.forEach(b -> deviceData.put((ByteBuffer) b.flip())); deviceData.flip(); return deviceData.asReadOnlyBuffer(); } private ByteBuffer nameBuffer(PiPipeconf pipeconf) { // Length of the name + name. String name = pipeconf.id().toString(); return ByteBuffer.allocate(Integer.BYTES + name.length()).order(ByteOrder.LITTLE_ENDIAN) .putInt(name.length()).put(name.getBytes(StandardCharsets.UTF_8)); } private ByteBuffer extensionBuffer(PiPipeconf pipeconf, ExtensionType extType) { if (!pipeconf.extension(extType).isPresent()) { log.warn("Missing extension {} in pipeconf {}", extType, pipeconf.id()); throw new ExtensionException(); } try { byte[] bytes = IOUtils.toByteArray(pipeconf.extension(extType).get()); // Length of the extension + bytes. return ByteBuffer.allocate(Integer.BYTES + bytes.length).order(ByteOrder.LITTLE_ENDIAN) .putInt(bytes.length).put(bytes); } catch (IOException ex) { log.warn("Unable to read extension {} from pipeconf {}: {}", extType, pipeconf.id(), ex.getMessage()); throw new ExtensionException(); } } private static class ExtensionException extends IllegalArgumentException { } }