blob: 6a6c2e940675a1caca5f17f502a6e6f701b5250e [file] [log] [blame]
Carmelo Casconed61fdb32017-10-30 10:09:57 -07001/*
2 * Copyright 2017-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.drivers.p4runtime;
18
19import org.onlab.util.SharedExecutors;
20import org.onosproject.net.DeviceId;
21import org.onosproject.net.driver.AbstractHandlerBehaviour;
22import org.onosproject.net.pi.model.PiPipeconf;
Carmelo Cascone87892e22017-11-13 16:01:29 -080023import org.onosproject.net.behaviour.PiPipelineProgrammable;
Carmelo Casconed61fdb32017-10-30 10:09:57 -070024import org.onosproject.p4runtime.api.P4RuntimeClient;
25import org.onosproject.p4runtime.api.P4RuntimeController;
26import org.slf4j.Logger;
27
28import java.nio.ByteBuffer;
29import java.util.Optional;
30import java.util.concurrent.CompletableFuture;
31import java.util.concurrent.ExecutionException;
32
33import static org.slf4j.LoggerFactory.getLogger;
34
35/**
36 * Abstract implementation of the PiPipelineProgrammable behaviours for a P4Runtime device.
37 */
38public abstract class AbstractP4RuntimePipelineProgrammable extends AbstractHandlerBehaviour
39 implements PiPipelineProgrammable {
40
41 protected final Logger log = getLogger(getClass());
42
43 /**
44 * Returns a byte buffer representing the target-specific device data to be used in the SetPipelineConfig message.
45 *
46 * @param pipeconf pipeconf
47 * @return byte buffer
48 */
49 public abstract ByteBuffer createDeviceDataBuffer(PiPipeconf pipeconf);
50
51 @Override
52 public CompletableFuture<Boolean> deployPipeconf(PiPipeconf pipeconf) {
53 return CompletableFuture.supplyAsync(
54 () -> doDeployConfig(pipeconf),
55 SharedExecutors.getPoolThreadExecutor());
56 }
57
58 private boolean doDeployConfig(PiPipeconf pipeconf) {
59
60 DeviceId deviceId = handler().data().deviceId();
61 P4RuntimeController controller = handler().get(P4RuntimeController.class);
62
63 if (!controller.hasClient(deviceId)) {
64 log.warn("Unable to find client for {}, aborting pipeconf deploy", deviceId);
65 return false;
66 }
67 P4RuntimeClient client = controller.getClient(deviceId);
68
69 ByteBuffer deviceDataBuffer = createDeviceDataBuffer(pipeconf);
70 if (deviceDataBuffer == null) {
71 // Hopefully the child class logged the problem.
72 return false;
73 }
74
75 try {
Carmelo Casconed61fdb32017-10-30 10:09:57 -070076 if (!client.initStreamChannel().get()) {
77 log.warn("Unable to init stream channel to {}.", deviceId);
78 return false;
79 }
80 } catch (InterruptedException | ExecutionException e) {
81 log.error("Exception while initializing stream channel on {}", deviceId, e);
82 return false;
83 }
84
Yi Tseng3e7f1452017-10-20 10:31:53 -070085 try {
86 if (!client.setPipelineConfig(pipeconf, deviceDataBuffer).get()) {
87 log.warn("Unable to deploy pipeconf {} to {}", pipeconf.id(), deviceId);
88 return false;
89 }
90 } catch (InterruptedException | ExecutionException e) {
91 log.error("Exception while deploying pipeconf to {}", deviceId, e);
92 return false;
93 }
Carmelo Casconed61fdb32017-10-30 10:09:57 -070094 return true;
95 }
96
97 @Override
98 public abstract Optional<PiPipeconf> getDefaultPipeconf();
99}