blob: 735c14262588fc50af2b24ab8239fdf8e5259407 [file] [log] [blame]
Carmelo Cascone59f57de2017-07-11 19:55:09 -04001/*
2 * Copyright 2017-present Open Networking Laboratory
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.bmv2;
18
19import org.onlab.util.SharedExecutors;
20import org.onosproject.net.DeviceId;
21import org.onosproject.net.driver.AbstractHandlerBehaviour;
22import org.onosproject.net.pi.model.PiPipeconf;
23import org.onosproject.net.pi.model.PiPipelineProgrammable;
24import org.onosproject.p4runtime.api.P4RuntimeClient;
25import org.onosproject.p4runtime.api.P4RuntimeController;
26import org.slf4j.Logger;
27
28import java.io.InputStream;
29import java.util.Optional;
30import java.util.concurrent.CompletableFuture;
31import java.util.concurrent.ExecutionException;
32
33import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.BMV2_JSON;
34import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.P4_INFO_TEXT;
35import static org.slf4j.LoggerFactory.getLogger;
36
37/**
38 * Implementation of the PiPipelineProgrammable for BMv2.
39 */
40public class Bmv2PipelineProgrammable extends AbstractHandlerBehaviour implements PiPipelineProgrammable {
41
42 private static final PiPipeconf DEFAULT_PIPECONF = new Bmv2DefaultPipeconf();
43
44 private final Logger log = getLogger(getClass());
45
46 @Override
47 public CompletableFuture<Boolean> deployPipeconf(PiPipeconf pipeconf) {
48
49 CompletableFuture<Boolean> result = new CompletableFuture<>();
50
51 SharedExecutors.getPoolThreadExecutor().submit(() -> result.complete(doDeployConfig(pipeconf)));
52
53 return result;
54 }
55
56 private boolean doDeployConfig(PiPipeconf pipeconf) {
57
58 P4RuntimeController controller = handler().get(P4RuntimeController.class);
59
60 DeviceId deviceId = handler().data().deviceId();
61
62 if (!controller.hasClient(deviceId)) {
63 log.warn("Unable to find client for {}, aborting pipeconf deploy", deviceId);
64 return false;
65
66 }
67
68 P4RuntimeClient client = controller.getClient(deviceId);
69
70 if (!pipeconf.extension(BMV2_JSON).isPresent()) {
71 log.warn("Missing BMv2 JSON config in pipeconf {}, aborting pipeconf deploy", pipeconf.id());
72 return false;
73 }
74
75 if (!pipeconf.extension(P4_INFO_TEXT).isPresent()) {
76 log.warn("Missing P4Info in pipeconf {}, aborting pipeconf deploy", pipeconf.id());
77 return false;
78 }
79
80 InputStream p4InfoStream = pipeconf.extension(P4_INFO_TEXT).get();
81 InputStream jsonStream = pipeconf.extension(BMV2_JSON).get();
82
83 try {
84 if (!client.setPipelineConfig(p4InfoStream, jsonStream).get()) {
85 log.warn("Unable to deploy pipeconf {} to {}", pipeconf.id(), deviceId);
86 return false;
87 }
88
89 // It would be more logical to have this performed at device handshake, but P4runtime would reject any
90 // command if a P4info has not been set first.
91 if (!client.initStreamChannel().get()) {
92 log.warn("Unable to init stream channel to {}.", deviceId);
93 return false;
94 }
95
96 } catch (InterruptedException | ExecutionException e) {
97 throw new RuntimeException(e);
98 }
99
100 return true;
101 }
102
103 @Override
104 public Optional<PiPipeconf> getDefaultPipeconf() {
105 return Optional.of(DEFAULT_PIPECONF);
106 }
107}