| /* |
| * 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.gnmi; |
| |
| import com.google.common.collect.Lists; |
| import com.google.common.collect.Maps; |
| import gnmi.Gnmi; |
| import gnmi.Gnmi.GetRequest; |
| import gnmi.Gnmi.GetResponse; |
| import org.onosproject.net.DefaultAnnotations; |
| import org.onosproject.net.PortNumber; |
| import org.onosproject.net.device.DefaultPortDescription; |
| import org.onosproject.net.device.DeviceDescription; |
| import org.onosproject.net.device.DeviceDescriptionDiscovery; |
| import org.onosproject.net.device.PortDescription; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| |
| import static gnmi.Gnmi.Path; |
| import static gnmi.Gnmi.PathElem; |
| import static gnmi.Gnmi.Update; |
| |
| /** |
| * Class that discovers the device description and ports of a device that |
| * supports the gNMI protocol and Openconfig models. |
| */ |
| public class OpenConfigGnmiDeviceDescriptionDiscovery |
| extends AbstractGnmiHandlerBehaviour |
| implements DeviceDescriptionDiscovery { |
| |
| private static final Logger log = LoggerFactory |
| .getLogger(OpenConfigGnmiDeviceDescriptionDiscovery.class); |
| |
| private static final String LAST_CHANGE = "last-change"; |
| |
| @Override |
| public DeviceDescription discoverDeviceDetails() { |
| return null; |
| } |
| |
| @Override |
| public List<PortDescription> discoverPortDetails() { |
| if (!setupBehaviour()) { |
| return Collections.emptyList(); |
| } |
| log.debug("Discovering port details on device {}", handler().data().deviceId()); |
| |
| final GetResponse response = getFutureWithDeadline( |
| client.get(buildPortStateRequest()), |
| "getting port details", GetResponse.getDefaultInstance()); |
| |
| final Map<String, DefaultPortDescription.Builder> ports = Maps.newHashMap(); |
| final Map<String, DefaultAnnotations.Builder> annotations = Maps.newHashMap(); |
| |
| // Creates port descriptions with port name and port number |
| response.getNotificationList() |
| .forEach(notification -> { |
| long timestamp = notification.getTimestamp(); |
| notification.getUpdateList().forEach(update -> { |
| // /interfaces/interface[name=ifName]/state/... |
| final String ifName = update.getPath().getElem(1) |
| .getKeyMap().get("name"); |
| if (!ports.containsKey(ifName)) { |
| ports.put(ifName, DefaultPortDescription.builder()); |
| annotations.put(ifName, DefaultAnnotations.builder()); |
| } |
| final DefaultPortDescription.Builder builder = ports.get(ifName); |
| final DefaultAnnotations.Builder annotationsBuilder = annotations.get(ifName); |
| parseInterfaceInfo(update, ifName, builder, annotationsBuilder, timestamp); |
| }); |
| }); |
| |
| final List<PortDescription> portDescriptionList = Lists.newArrayList(); |
| ports.forEach((key, value) -> { |
| DefaultAnnotations annotation = annotations.get(key).build(); |
| portDescriptionList.add(value.annotations(annotation).build()); |
| }); |
| return portDescriptionList; |
| } |
| |
| private GetRequest buildPortStateRequest() { |
| Path path = Path.newBuilder() |
| .addElem(PathElem.newBuilder().setName("interfaces").build()) |
| .addElem(PathElem.newBuilder().setName("interface").putKey("name", "...").build()) |
| .addElem(PathElem.newBuilder().setName("state").build()) |
| .build(); |
| return GetRequest.newBuilder() |
| .addPath(path) |
| .setType(GetRequest.DataType.ALL) |
| .setEncoding(Gnmi.Encoding.PROTO) |
| .build(); |
| } |
| |
| /** |
| * Parses the interface information. |
| * |
| * @param update the update received |
| */ |
| private void parseInterfaceInfo(Update update, |
| String ifName, |
| DefaultPortDescription.Builder builder, |
| DefaultAnnotations.Builder annotationsBuilder, |
| long timestamp) { |
| |
| |
| final Path path = update.getPath(); |
| final List<PathElem> elems = path.getElemList(); |
| final Gnmi.TypedValue val = update.getVal(); |
| if (elems.size() == 4) { |
| // /interfaces/interface/state/ifindex |
| // /interfaces/interface/state/oper-status |
| final String pathElemName = elems.get(3).getName(); |
| switch (pathElemName) { |
| case "ifindex": // port number |
| builder.withPortNumber(PortNumber.portNumber(val.getUintVal(), ifName)); |
| return; |
| case "oper-status": |
| builder.isEnabled(parseOperStatus(val.getStringVal())); |
| annotationsBuilder.set(LAST_CHANGE, String.valueOf(timestamp)); |
| return; |
| default: |
| break; |
| } |
| } else if (elems.size() == 5) { |
| // /interfaces/interface/ethernet/config/port-speed |
| final String pathElemName = elems.get(4).getName(); |
| if (pathElemName.equals("port-speed")) { |
| builder.portSpeed(parsePortSpeed(val.getStringVal())); |
| return; |
| } |
| } |
| log.debug("Unknown path when parsing interface info: {}", path); |
| } |
| |
| private boolean parseOperStatus(String operStatus) { |
| switch (operStatus) { |
| case "UP": |
| return true; |
| case "DOWN": |
| default: |
| return false; |
| } |
| } |
| |
| private long parsePortSpeed(String speed) { |
| log.debug("Speed from config {}", speed); |
| switch (speed) { |
| case "SPEED_10MB": |
| return 10; |
| case "SPEED_100MB": |
| return 100; |
| case "SPEED_1GB": |
| return 1000; |
| case "SPEED_10GB": |
| return 10000; |
| case "SPEED_25GB": |
| return 25000; |
| case "SPEED_40GB": |
| return 40000; |
| case "SPEED_50GB": |
| return 50000; |
| case "SPEED_100GB": |
| return 100000; |
| default: |
| log.warn("Unrecognized port speed string '{}'", speed); |
| return 1000; |
| } |
| } |
| } |