blob: 526c333763ea21b468ad36b1fe653ce9e79d7a68 [file] [log] [blame]
Yi Tseng27851e32018-11-01 18:30:04 -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.gnmi;
18
19import com.google.common.collect.Lists;
20import com.google.common.collect.Maps;
21import gnmi.Gnmi;
22import gnmi.Gnmi.GetRequest;
23import gnmi.Gnmi.GetResponse;
24import org.onosproject.net.DefaultAnnotations;
25import org.onosproject.net.PortNumber;
26import org.onosproject.net.device.DefaultPortDescription;
27import org.onosproject.net.device.DeviceDescription;
28import org.onosproject.net.device.DeviceDescriptionDiscovery;
29import org.onosproject.net.device.PortDescription;
30import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
32
Yi Tseng27851e32018-11-01 18:30:04 -070033import java.util.Collections;
34import java.util.List;
35import java.util.Map;
Yi Tseng27851e32018-11-01 18:30:04 -070036
37import static gnmi.Gnmi.Path;
38import static gnmi.Gnmi.PathElem;
39import static gnmi.Gnmi.Update;
40
41/**
42 * Class that discovers the device description and ports of a device that
43 * supports the gNMI protocol and Openconfig models.
44 */
45public class OpenConfigGnmiDeviceDescriptionDiscovery
46 extends AbstractGnmiHandlerBehaviour
47 implements DeviceDescriptionDiscovery {
48
Yi Tseng27851e32018-11-01 18:30:04 -070049 private static final Logger log = LoggerFactory
50 .getLogger(OpenConfigGnmiDeviceDescriptionDiscovery.class);
51
52 @Override
53 public DeviceDescription discoverDeviceDetails() {
54 return null;
55 }
56
57 @Override
58 public List<PortDescription> discoverPortDetails() {
59 if (!setupBehaviour()) {
60 return Collections.emptyList();
61 }
62 log.debug("Discovering port details on device {}", handler().data().deviceId());
63
Yi Tsengd7716482018-10-31 15:34:30 -070064 final GetResponse response = getFutureWithDeadline(
65 client.get(buildPortStateRequest()),
66 "getting port details", GetResponse.getDefaultInstance());
Yi Tseng27851e32018-11-01 18:30:04 -070067
Yi Tsengd7716482018-10-31 15:34:30 -070068 final Map<String, DefaultPortDescription.Builder> ports = Maps.newHashMap();
69 final Map<String, DefaultAnnotations.Builder> annotations = Maps.newHashMap();
Yi Tseng27851e32018-11-01 18:30:04 -070070
71 // Creates port descriptions with port name and port number
72 response.getNotificationList()
73 .stream()
74 .flatMap(notification -> notification.getUpdateList().stream())
75 .forEach(update -> {
76 // /interfaces/interface[name=ifName]/state/...
Yi Tsengd7716482018-10-31 15:34:30 -070077 final String ifName = update.getPath().getElem(1)
78 .getKeyMap().get("name");
Yi Tseng27851e32018-11-01 18:30:04 -070079 if (!ports.containsKey(ifName)) {
80 ports.put(ifName, DefaultPortDescription.builder());
81 annotations.put(ifName, DefaultAnnotations.builder());
82 }
Yi Tsengd7716482018-10-31 15:34:30 -070083 final DefaultPortDescription.Builder builder = ports.get(ifName);
84 final DefaultAnnotations.Builder annotationsBuilder = annotations.get(ifName);
Yi Tseng27851e32018-11-01 18:30:04 -070085 parseInterfaceInfo(update, ifName, builder, annotationsBuilder);
86 });
87
Yi Tsengd7716482018-10-31 15:34:30 -070088 final List<PortDescription> portDescriptionList = Lists.newArrayList();
Yi Tseng27851e32018-11-01 18:30:04 -070089 ports.forEach((key, value) -> {
90 DefaultAnnotations annotation = annotations.get(key).build();
91 portDescriptionList.add(value.annotations(annotation).build());
92 });
93 return portDescriptionList;
94 }
95
96 private GetRequest buildPortStateRequest() {
97 Path path = Path.newBuilder()
98 .addElem(PathElem.newBuilder().setName("interfaces").build())
99 .addElem(PathElem.newBuilder().setName("interface").putKey("name", "...").build())
100 .addElem(PathElem.newBuilder().setName("state").build())
101 .build();
102 return GetRequest.newBuilder()
103 .addPath(path)
104 .setType(GetRequest.DataType.ALL)
105 .setEncoding(Gnmi.Encoding.PROTO)
106 .build();
107 }
108
109 /**
110 * Parses the interface information.
111 *
Yi Tsengd7716482018-10-31 15:34:30 -0700112 * @param update the update received
Yi Tseng27851e32018-11-01 18:30:04 -0700113 */
114 private void parseInterfaceInfo(Update update,
115 String ifName,
116 DefaultPortDescription.Builder builder,
117 DefaultAnnotations.Builder annotationsBuilder) {
118
119
Yi Tsengd7716482018-10-31 15:34:30 -0700120 final Path path = update.getPath();
121 final List<PathElem> elems = path.getElemList();
122 final Gnmi.TypedValue val = update.getVal();
Yi Tseng27851e32018-11-01 18:30:04 -0700123 if (elems.size() == 4) {
124 // /interfaces/interface/state/ifindex
125 // /interfaces/interface/state/oper-status
Yi Tsengd7716482018-10-31 15:34:30 -0700126 final String pathElemName = elems.get(3).getName();
Yi Tseng27851e32018-11-01 18:30:04 -0700127 switch (pathElemName) {
128 case "ifindex": // port number
129 builder.withPortNumber(PortNumber.portNumber(val.getUintVal(), ifName));
Yi Tsengd7716482018-10-31 15:34:30 -0700130 return;
Yi Tseng27851e32018-11-01 18:30:04 -0700131 case "oper-status":
132 builder.isEnabled(parseOperStatus(val.getStringVal()));
Yi Tsengd7716482018-10-31 15:34:30 -0700133 return;
Yi Tseng27851e32018-11-01 18:30:04 -0700134 default:
Yi Tseng27851e32018-11-01 18:30:04 -0700135 break;
136 }
Yi Tsengd7716482018-10-31 15:34:30 -0700137 } else if (elems.size() == 5) {
Yi Tseng27851e32018-11-01 18:30:04 -0700138 // /interfaces/interface/ethernet/config/port-speed
Yi Tsengd7716482018-10-31 15:34:30 -0700139 final String pathElemName = elems.get(4).getName();
140 if (pathElemName.equals("port-speed")) {
141 builder.portSpeed(parsePortSpeed(val.getStringVal()));
142 return;
Yi Tseng27851e32018-11-01 18:30:04 -0700143 }
144 }
Yi Tsengd7716482018-10-31 15:34:30 -0700145 log.debug("Unknown path when parsing interface info: {}", path);
Yi Tseng27851e32018-11-01 18:30:04 -0700146 }
147
148 private boolean parseOperStatus(String operStatus) {
149 switch (operStatus) {
150 case "UP":
151 return true;
152 case "DOWN":
153 default:
154 return false;
155 }
156 }
157
158 private long parsePortSpeed(String speed) {
159 log.debug("Speed from config {}", speed);
160 switch (speed) {
161 case "SPEED_10MB":
162 return 10;
163 case "SPEED_100MB":
164 return 100;
165 case "SPEED_1GB":
166 return 1000;
167 case "SPEED_10GB":
168 return 10000;
169 case "SPEED_25GB":
170 return 25000;
171 case "SPEED_40GB":
172 return 40000;
173 case "SPEED_50GB":
174 return 50000;
175 case "SPEED_100GB":
176 return 100000;
177 default:
Yi Tsengd7716482018-10-31 15:34:30 -0700178 log.warn("Unrecognized port speed string '{}'", speed);
Yi Tseng27851e32018-11-01 18:30:04 -0700179 return 1000;
180 }
181 }
182}