blob: 58cab8ade4b04ee99922cecaa92d981924a667b7 [file] [log] [blame]
Andrea Campanella241896c2017-05-10 13:11:04 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Andrea Campanella241896c2017-05-10 13:11:04 -07003 *
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
Andrea Campanella0288c872017-08-07 18:32:51 +020017package org.onosproject.drivers.p4runtime;
Andrea Campanella241896c2017-05-10 13:11:04 -070018
Andrea Campanella378e21a2017-06-07 12:09:59 +020019import org.onosproject.net.DeviceId;
Andrea Campanella241896c2017-05-10 13:11:04 -070020import org.onosproject.net.MastershipRole;
Andrea Campanella1e573442018-05-17 17:07:13 +020021import org.onosproject.net.device.ChannelListener;
Andrea Campanella241896c2017-05-10 13:11:04 -070022import org.onosproject.net.device.DeviceHandshaker;
Carmelo Cascone59f57de2017-07-11 19:55:09 -040023import org.onosproject.p4runtime.api.P4RuntimeController;
Andrea Campanella241896c2017-05-10 13:11:04 -070024
25import java.util.concurrent.CompletableFuture;
26
Andrea Campanella241896c2017-05-10 13:11:04 -070027/**
Carmelo Casconee3a7c742017-09-01 01:25:52 +020028 * Implementation of DeviceHandshaker for P4Runtime.
Andrea Campanella241896c2017-05-10 13:11:04 -070029 */
Carmelo Casconee3a7c742017-09-01 01:25:52 +020030public class P4RuntimeHandshaker extends AbstractP4RuntimeHandlerBehaviour implements DeviceHandshaker {
Andrea Campanella241896c2017-05-10 13:11:04 -070031
Carmelo Cascone59f57de2017-07-11 19:55:09 -040032 // TODO: consider abstract class with empty connect method and implementation into a protected one for reusability.
33
Andrea Campanella241896c2017-05-10 13:11:04 -070034 @Override
35 public CompletableFuture<Boolean> connect() {
Carmelo Cascone59f57de2017-07-11 19:55:09 -040036 return CompletableFuture.supplyAsync(this::doConnect);
37 }
38
39 private boolean doConnect() {
Carmelo Casconee3a7c742017-09-01 01:25:52 +020040 return super.createClient();
Andrea Campanella241896c2017-05-10 13:11:04 -070041 }
42
43 @Override
44 public CompletableFuture<Boolean> disconnect() {
Carmelo Cascone59f57de2017-07-11 19:55:09 -040045 return CompletableFuture.supplyAsync(() -> {
46 P4RuntimeController controller = handler().get(P4RuntimeController.class);
47 DeviceId deviceId = handler().data().deviceId();
48 controller.removeClient(deviceId);
49 return true;
50 });
Andrea Campanella241896c2017-05-10 13:11:04 -070051 }
52
53 @Override
54 public CompletableFuture<Boolean> isReachable() {
Carmelo Cascone59f57de2017-07-11 19:55:09 -040055 return CompletableFuture.supplyAsync(() -> {
56 P4RuntimeController controller = handler().get(P4RuntimeController.class);
57 DeviceId deviceId = handler().data().deviceId();
58 return controller.isReacheable(deviceId);
59 });
Andrea Campanella241896c2017-05-10 13:11:04 -070060 }
61
62 @Override
63 public CompletableFuture<MastershipRole> roleChanged(MastershipRole newRole) {
Yi Tseng3e7f1452017-10-20 10:31:53 -070064 deviceId = handler().data().deviceId();
65 controller = handler().get(P4RuntimeController.class);
Andrea Campanella241896c2017-05-10 13:11:04 -070066 CompletableFuture<MastershipRole> result = new CompletableFuture<>();
Yi Tseng3e7f1452017-10-20 10:31:53 -070067
68 client = controller.getClient(deviceId);
69 if (client == null || !controller.isReacheable(deviceId)) {
Andrea Campanella14e196d2017-07-24 18:11:36 +020070 result.complete(MastershipRole.NONE);
Yi Tseng3e7f1452017-10-20 10:31:53 -070071 return result;
72 }
73 if (newRole.equals(MastershipRole.MASTER)) {
74 client.sendMasterArbitrationUpdate().thenAcceptAsync(success -> {
75 if (!success) {
76 log.warn("Device {} arbitration failed", deviceId);
77 result.complete(MastershipRole.STANDBY);
78 } else {
79 result.complete(MastershipRole.MASTER);
80 }
81 });
82 } else {
83 // Since we don't need to do anything, we can complete it directly
84 // Spec: The client with the highest election id is referred to as the
85 // "master", while all other clients are referred to as "slaves".
86 result.complete(newRole);
87 }
Andrea Campanella241896c2017-05-10 13:11:04 -070088 return result;
89 }
Andrea Campanella1e573442018-05-17 17:07:13 +020090
91 @Override
92 public void addChannelListener(ChannelListener listener) {
93 controller.addChannelListener(deviceId, listener);
94 }
95
96 @Override
97 public void removeChannelListener(ChannelListener listener) {
98 controller.removeChannelListener(deviceId, listener);
99 }
Andrea Campanella241896c2017-05-10 13:11:04 -0700100}