blob: 5326861bcffe1c6a78aed575b1f9f2e6948c8489 [file] [log] [blame]
Carmelo Casconee3a7c742017-09-01 01:25:52 +02001/*
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
Carmelo Cascone3977ea42019-02-28 13:43:42 -080019import com.google.common.base.Strings;
Carmelo Casconee3a7c742017-09-01 01:25:52 +020020import org.onosproject.net.Device;
21import org.onosproject.net.DeviceId;
Carmelo Cascone3977ea42019-02-28 13:43:42 -080022import org.onosproject.net.config.NetworkConfigService;
23import org.onosproject.net.config.basics.BasicDeviceConfig;
Carmelo Casconee3a7c742017-09-01 01:25:52 +020024import org.onosproject.net.device.DeviceService;
25import org.onosproject.net.driver.AbstractHandlerBehaviour;
26import org.onosproject.net.pi.model.PiPipeconf;
Carmelo Cascone158b8c42018-07-04 19:42:37 +020027import org.onosproject.net.pi.model.PiPipelineInterpreter;
Carmelo Cascone39c28ca2017-11-15 13:03:57 -080028import org.onosproject.net.pi.service.PiPipeconfService;
29import org.onosproject.net.pi.service.PiTranslationService;
Carmelo Casconee3a7c742017-09-01 01:25:52 +020030import org.onosproject.p4runtime.api.P4RuntimeClient;
Yi Tseng2a340f72018-11-02 16:52:47 -070031import org.onosproject.p4runtime.api.P4RuntimeClientKey;
Carmelo Casconee3a7c742017-09-01 01:25:52 +020032import org.onosproject.p4runtime.api.P4RuntimeController;
33import org.slf4j.Logger;
34import org.slf4j.LoggerFactory;
35
Carmelo Cascone3977ea42019-02-28 13:43:42 -080036import java.net.URI;
37import java.net.URISyntaxException;
Carmelo Casconee5b28722018-06-22 17:28:28 +020038
Carmelo Cascone3da671a2018-02-12 10:43:35 -080039import static com.google.common.base.Preconditions.checkNotNull;
40
Carmelo Casconee3a7c742017-09-01 01:25:52 +020041/**
42 * Abstract implementation of a behaviour handler for a P4Runtime device.
43 */
44public class AbstractP4RuntimeHandlerBehaviour extends AbstractHandlerBehaviour {
45
Carmelo Casconee3a7c742017-09-01 01:25:52 +020046 protected final Logger log = LoggerFactory.getLogger(getClass());
47
48 // Initialized by setupBehaviour()
49 protected DeviceId deviceId;
50 protected DeviceService deviceService;
51 protected Device device;
52 protected P4RuntimeController controller;
53 protected PiPipeconf pipeconf;
54 protected P4RuntimeClient client;
Yi Tsengd7716482018-10-31 15:34:30 -070055 protected PiTranslationService translationService;
Carmelo Casconee3a7c742017-09-01 01:25:52 +020056
57 /**
Carmelo Cascone3da671a2018-02-12 10:43:35 -080058 * Initializes this behaviour attributes. Returns true if the operation was
Carmelo Cascone4c289b72019-01-22 15:30:45 -080059 * successful, false otherwise. This method assumes that the P4Runtime
Carmelo Cascone3da671a2018-02-12 10:43:35 -080060 * controller already has a client for this device and that the device has
61 * been created in the core.
Carmelo Casconee3a7c742017-09-01 01:25:52 +020062 *
63 * @return true if successful, false otherwise
64 */
65 protected boolean setupBehaviour() {
66 deviceId = handler().data().deviceId();
67
68 deviceService = handler().get(DeviceService.class);
69 device = deviceService.getDevice(deviceId);
70 if (device == null) {
Carmelo Cascone3977ea42019-02-28 13:43:42 -080071 log.warn("Unable to find device with id {}", deviceId);
Carmelo Casconee3a7c742017-09-01 01:25:52 +020072 return false;
73 }
74
75 controller = handler().get(P4RuntimeController.class);
Carmelo Cascone158b8c42018-07-04 19:42:37 +020076 client = controller.getClient(deviceId);
77 if (client == null) {
Carmelo Cascone3977ea42019-02-28 13:43:42 -080078 log.warn("Unable to find client for {}", deviceId);
Carmelo Casconee3a7c742017-09-01 01:25:52 +020079 return false;
80 }
Carmelo Casconee3a7c742017-09-01 01:25:52 +020081
82 PiPipeconfService piPipeconfService = handler().get(PiPipeconfService.class);
Carmelo Cascone3977ea42019-02-28 13:43:42 -080083 if (!piPipeconfService.getPipeconf(deviceId).isPresent()) {
Carmelo Casconee5b28722018-06-22 17:28:28 +020084 log.warn("Unable to get assigned pipeconf for {} (mapping " +
Carmelo Cascone3977ea42019-02-28 13:43:42 -080085 "missing in PiPipeconfService)",
Carmelo Casconee5b28722018-06-22 17:28:28 +020086 deviceId);
Carmelo Casconee3a7c742017-09-01 01:25:52 +020087 return false;
88 }
Carmelo Cascone3977ea42019-02-28 13:43:42 -080089 pipeconf = piPipeconfService.getPipeconf(deviceId).get();
Carmelo Casconee3a7c742017-09-01 01:25:52 +020090
Yi Tsengd7716482018-10-31 15:34:30 -070091 translationService = handler().get(PiTranslationService.class);
Carmelo Cascone87b9b392017-10-02 18:33:20 +020092
Carmelo Casconee3a7c742017-09-01 01:25:52 +020093 return true;
94 }
95
96 /**
Carmelo Cascone158b8c42018-07-04 19:42:37 +020097 * Returns an instance of the interpreter implementation for this device,
98 * null if an interpreter cannot be retrieved.
99 *
100 * @return interpreter or null
101 */
102 PiPipelineInterpreter getInterpreter() {
103 if (!device.is(PiPipelineInterpreter.class)) {
104 log.warn("Unable to get interpreter for {}, missing behaviour",
105 deviceId);
106 return null;
107 }
108 return device.as(PiPipelineInterpreter.class);
109 }
110
111 /**
Carmelo Cascone3977ea42019-02-28 13:43:42 -0800112 * Returns a P4Runtime client previsouly created for this device, null if
113 * such client does not exist.
Carmelo Casconee3a7c742017-09-01 01:25:52 +0200114 *
Carmelo Casconee5b28722018-06-22 17:28:28 +0200115 * @return client or null
Carmelo Casconee3a7c742017-09-01 01:25:52 +0200116 */
Carmelo Cascone3977ea42019-02-28 13:43:42 -0800117 P4RuntimeClient getClientByKey() {
118 final P4RuntimeClientKey clientKey = clientKey();
119 if (clientKey == null) {
120 return null;
121 }
122 return handler().get(P4RuntimeController.class).getClient(clientKey);
123 }
124
125 protected P4RuntimeClientKey clientKey() {
Carmelo Casconee3a7c742017-09-01 01:25:52 +0200126 deviceId = handler().data().deviceId();
Carmelo Casconee3a7c742017-09-01 01:25:52 +0200127
Carmelo Cascone3977ea42019-02-28 13:43:42 -0800128 final BasicDeviceConfig cfg = handler().get(NetworkConfigService.class)
129 .getConfig(deviceId, BasicDeviceConfig.class);
130 if (cfg == null || Strings.isNullOrEmpty(cfg.managementAddress())) {
131 log.error("Missing or invalid config for {}, cannot derive " +
132 "P4Runtime server endpoints", deviceId);
Carmelo Casconee5b28722018-06-22 17:28:28 +0200133 return null;
Carmelo Casconee3a7c742017-09-01 01:25:52 +0200134 }
135
Carmelo Cascone158b8c42018-07-04 19:42:37 +0200136 try {
Carmelo Cascone3977ea42019-02-28 13:43:42 -0800137 return new P4RuntimeClientKey(
138 deviceId, new URI(cfg.managementAddress()));
139 } catch (URISyntaxException e) {
140 log.error("Management address of {} is not a valid URI: {}",
141 deviceId, cfg.managementAddress());
Carmelo Casconee5b28722018-06-22 17:28:28 +0200142 return null;
143 }
Carmelo Casconee3a7c742017-09-01 01:25:52 +0200144 }
Carmelo Cascone3da671a2018-02-12 10:43:35 -0800145
146 /**
Carmelo Casconee5b28722018-06-22 17:28:28 +0200147 * Returns the value of the given driver property, if present, otherwise
148 * returns the given default value.
Carmelo Cascone3da671a2018-02-12 10:43:35 -0800149 *
Carmelo Casconee5b28722018-06-22 17:28:28 +0200150 * @param propName property name
Carmelo Cascone3da671a2018-02-12 10:43:35 -0800151 * @param defaultVal default value
152 * @return boolean
153 */
Yi Tsengd7716482018-10-31 15:34:30 -0700154 boolean driverBoolProperty(String propName, boolean defaultVal) {
Carmelo Cascone3da671a2018-02-12 10:43:35 -0800155 checkNotNull(propName);
156 if (handler().driver().getProperty(propName) == null) {
157 return defaultVal;
158 } else {
159 return Boolean.parseBoolean(handler().driver().getProperty(propName));
160 }
161 }
Carmelo Casconee3a7c742017-09-01 01:25:52 +0200162}