blob: 5e62e09ceeec523536a6949c18b2d9ac563c5545 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.provider.of.device.impl;
tomb5a46e62014-08-26 14:20:00 -070017
sangho538108b2015-04-08 14:29:20 -070018import com.google.common.collect.Maps;
19import com.google.common.collect.Sets;
Ayaka Koshibe5460d622015-05-14 12:19:19 -070020
tomb5a46e62014-08-26 14:20:00 -070021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
Thomas Vachuskab52a0142015-04-21 17:48:15 -070026import org.onosproject.net.AnnotationKeys;
Brian O'Connorabafb502014-12-02 22:26:20 -080027import org.onosproject.net.DefaultAnnotations;
28import org.onosproject.net.Device;
29import org.onosproject.net.DeviceId;
30import org.onosproject.net.MastershipRole;
31import org.onosproject.net.Port;
32import org.onosproject.net.PortNumber;
33import org.onosproject.net.SparseAnnotations;
34import org.onosproject.net.device.DefaultDeviceDescription;
35import org.onosproject.net.device.DefaultPortDescription;
sangho538108b2015-04-08 14:29:20 -070036import org.onosproject.net.device.DefaultPortStatistics;
Brian O'Connorabafb502014-12-02 22:26:20 -080037import org.onosproject.net.device.DeviceDescription;
38import org.onosproject.net.device.DeviceProvider;
39import org.onosproject.net.device.DeviceProviderRegistry;
40import org.onosproject.net.device.DeviceProviderService;
41import org.onosproject.net.device.PortDescription;
sangho538108b2015-04-08 14:29:20 -070042import org.onosproject.net.device.PortStatistics;
Brian O'Connorabafb502014-12-02 22:26:20 -080043import org.onosproject.net.provider.AbstractProvider;
44import org.onosproject.net.provider.ProviderId;
45import org.onosproject.openflow.controller.Dpid;
46import org.onosproject.openflow.controller.OpenFlowController;
sangho538108b2015-04-08 14:29:20 -070047import org.onosproject.openflow.controller.OpenFlowEventListener;
Ayaka Koshibe5460d622015-05-14 12:19:19 -070048import org.onosproject.openflow.controller.OpenFlowOpticalSwitch;
Brian O'Connorabafb502014-12-02 22:26:20 -080049import org.onosproject.openflow.controller.OpenFlowSwitch;
50import org.onosproject.openflow.controller.OpenFlowSwitchListener;
Ayaka Koshibe5460d622015-05-14 12:19:19 -070051import org.onosproject.openflow.controller.PortDescPropertyType;
Brian O'Connorabafb502014-12-02 22:26:20 -080052import org.onosproject.openflow.controller.RoleState;
alshabib7911a052014-10-16 17:49:37 -070053import org.onlab.packet.ChassisId;
Ayaka Koshibee8708e32014-10-22 13:40:18 -070054import org.projectfloodlight.openflow.protocol.OFFactory;
sangho538108b2015-04-08 14:29:20 -070055import org.projectfloodlight.openflow.protocol.OFMessage;
alshabib4680bb62014-09-04 17:15:08 -070056import org.projectfloodlight.openflow.protocol.OFPortConfig;
alshabib25c8eec2014-09-04 16:41:31 -070057import org.projectfloodlight.openflow.protocol.OFPortDesc;
Thomas Vachuskad16ce182014-10-29 17:25:29 -070058import org.projectfloodlight.openflow.protocol.OFPortFeatures;
Ayaka Koshibe5460d622015-05-14 12:19:19 -070059import org.projectfloodlight.openflow.protocol.OFPortOptical;
alshabibafc514a2014-12-01 14:44:05 -080060import org.projectfloodlight.openflow.protocol.OFPortReason;
alshabib4680bb62014-09-04 17:15:08 -070061import org.projectfloodlight.openflow.protocol.OFPortState;
sangho538108b2015-04-08 14:29:20 -070062import org.projectfloodlight.openflow.protocol.OFPortStatsEntry;
63import org.projectfloodlight.openflow.protocol.OFPortStatsReply;
alshabiba14f3642014-09-05 09:31:31 -070064import org.projectfloodlight.openflow.protocol.OFPortStatus;
sangho538108b2015-04-08 14:29:20 -070065import org.projectfloodlight.openflow.protocol.OFStatsReply;
66import org.projectfloodlight.openflow.protocol.OFStatsType;
Thomas Vachuskad16ce182014-10-29 17:25:29 -070067import org.projectfloodlight.openflow.protocol.OFVersion;
68import org.projectfloodlight.openflow.types.PortSpeed;
tomb5a46e62014-08-26 14:20:00 -070069import org.slf4j.Logger;
tom5f38b3a2014-08-27 23:50:54 -070070
tom782a7cf2014-09-11 23:58:38 -070071import java.util.ArrayList;
sangho538108b2015-04-08 14:29:20 -070072import java.util.Collection;
73import java.util.Collections;
74import java.util.HashMap;
75import java.util.HashSet;
tom782a7cf2014-09-11 23:58:38 -070076import java.util.List;
77
Ray Milkeye0fade72015-01-15 13:29:47 -080078import com.google.common.base.Strings;
79
Brian O'Connorabafb502014-12-02 22:26:20 -080080import static org.onosproject.net.DeviceId.deviceId;
81import static org.onosproject.net.Port.Type.COPPER;
82import static org.onosproject.net.Port.Type.FIBER;
83import static org.onosproject.openflow.controller.Dpid.dpid;
84import static org.onosproject.openflow.controller.Dpid.uri;
tom782a7cf2014-09-11 23:58:38 -070085import static org.slf4j.LoggerFactory.getLogger;
86
tomb5a46e62014-08-26 14:20:00 -070087/**
tomb1260e42014-08-26 18:39:57 -070088 * Provider which uses an OpenFlow controller to detect network
tome06f8552014-08-26 16:58:42 -070089 * infrastructure devices.
tomb5a46e62014-08-26 14:20:00 -070090 */
tomb1260e42014-08-26 18:39:57 -070091@Component(immediate = true)
tomab21e7c2014-08-26 15:23:08 -070092public class OpenFlowDeviceProvider extends AbstractProvider implements DeviceProvider {
tomb5a46e62014-08-26 14:20:00 -070093
alshabiba89cc582014-09-09 16:43:00 -070094 private static final Logger LOG = getLogger(OpenFlowDeviceProvider.class);
Thomas Vachuskad16ce182014-10-29 17:25:29 -070095 private static final long MBPS = 1_000 * 1_000;
tomb5a46e62014-08-26 14:20:00 -070096
97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom96dfcab2014-08-28 09:26:03 -070098 protected DeviceProviderRegistry providerRegistry;
tomab21e7c2014-08-26 15:23:08 -070099
tom5f38b3a2014-08-27 23:50:54 -0700100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected OpenFlowController controller;
102
tomab21e7c2014-08-26 15:23:08 -0700103 private DeviceProviderService providerService;
tomb5a46e62014-08-26 14:20:00 -0700104
sangho538108b2015-04-08 14:29:20 -0700105 private final InternalDeviceProvider listener = new InternalDeviceProvider();
106
107 // TODO: We need to make the poll interval configurable.
108 static final int POLL_INTERVAL = 10;
109
110 private HashMap<Dpid, PortStatsCollector> collectors = Maps.newHashMap();
tomd40fc7a2014-09-04 16:41:10 -0700111
tomab21e7c2014-08-26 15:23:08 -0700112 /**
113 * Creates an OpenFlow device provider.
114 */
115 public OpenFlowDeviceProvider() {
Brian O'Connorabafb502014-12-02 22:26:20 -0800116 super(new ProviderId("of", "org.onosproject.provider.openflow"));
tomab21e7c2014-08-26 15:23:08 -0700117 }
118
tomb5a46e62014-08-26 14:20:00 -0700119 @Activate
120 public void activate() {
tom96dfcab2014-08-28 09:26:03 -0700121 providerService = providerRegistry.register(this);
tomd40fc7a2014-09-04 16:41:10 -0700122 controller.addListener(listener);
sangho538108b2015-04-08 14:29:20 -0700123 controller.addEventListener(listener);
alshabibc944fd02014-09-10 17:55:17 -0700124 for (OpenFlowSwitch sw : controller.getSwitches()) {
Yuta HIGUCHIac2972a2014-11-18 12:58:52 -0800125 try {
126 listener.switchAdded(new Dpid(sw.getId()));
127 } catch (Exception e) {
128 LOG.warn("Failed initially adding {} : {}", sw.getStringId(), e.getMessage());
129 LOG.debug("Error details:", e);
130 // disconnect to trigger switch-add later
131 sw.disconnectSwitch();
132 }
sangho538108b2015-04-08 14:29:20 -0700133 PortStatsCollector psc = new PortStatsCollector(sw, POLL_INTERVAL);
134 psc.start();
135 collectors.put(new Dpid(sw.getId()), psc);
alshabibc944fd02014-09-10 17:55:17 -0700136 }
alshabiba89cc582014-09-09 16:43:00 -0700137 LOG.info("Started");
tomb5a46e62014-08-26 14:20:00 -0700138 }
139
140 @Deactivate
141 public void deactivate() {
tom96dfcab2014-08-28 09:26:03 -0700142 providerRegistry.unregister(this);
tomd40fc7a2014-09-04 16:41:10 -0700143 controller.removeListener(listener);
tomab21e7c2014-08-26 15:23:08 -0700144 providerService = null;
alshabibc944fd02014-09-10 17:55:17 -0700145
alshabiba89cc582014-09-09 16:43:00 -0700146 LOG.info("Stopped");
tomb5a46e62014-08-26 14:20:00 -0700147 }
148
Ayaka Koshibee60d4522014-10-28 15:07:00 -0700149
150 @Override
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700151 public boolean isReachable(DeviceId deviceId) {
152 OpenFlowSwitch sw = controller.getSwitch(dpid(deviceId.uri()));
Yuta HIGUCHI69a27352014-10-31 15:48:37 -0700153 if (sw == null || !sw.isConnected()) {
Ayaka Koshibee60d4522014-10-28 15:07:00 -0700154 return false;
155 }
156 return true;
Ayaka Koshibee60d4522014-10-28 15:07:00 -0700157 }
158
tomab21e7c2014-08-26 15:23:08 -0700159 @Override
Ayaka Koshibe78bcbc12014-11-19 14:28:58 -0800160 public void triggerProbe(DeviceId deviceId) {
Yuta HIGUCHI802d0e82014-10-31 16:07:37 -0700161 LOG.info("Triggering probe on device {}", deviceId);
Ayaka Koshibee8708e32014-10-22 13:40:18 -0700162
Yuta HIGUCHI802d0e82014-10-31 16:07:37 -0700163 final Dpid dpid = dpid(deviceId.uri());
164 OpenFlowSwitch sw = controller.getSwitch(dpid);
165 if (sw == null || !sw.isConnected()) {
Ayaka Koshibe78bcbc12014-11-19 14:28:58 -0800166 LOG.error("Failed to probe device {} on sw={}", deviceId, sw);
Yuta HIGUCHI802d0e82014-10-31 16:07:37 -0700167 providerService.deviceDisconnected(deviceId);
168 } else {
Ayaka Koshibe78bcbc12014-11-19 14:28:58 -0800169 LOG.trace("Confirmed device {} connection", deviceId);
Yuta HIGUCHI802d0e82014-10-31 16:07:37 -0700170 }
Ayaka Koshibee8708e32014-10-22 13:40:18 -0700171
Ayaka Koshibee60d4522014-10-28 15:07:00 -0700172 // Prompt an update of port information. We can use any XID for this.
Ayaka Koshibee8708e32014-10-22 13:40:18 -0700173 OFFactory fact = sw.factory();
174 switch (fact.getVersion()) {
175 case OF_10:
176 sw.sendMsg(fact.buildFeaturesRequest().setXid(0).build());
177 break;
178 case OF_13:
179 sw.sendMsg(fact.buildPortDescStatsRequest().setXid(0).build());
180 break;
181 default:
182 LOG.warn("Unhandled protocol version");
183 }
tomab21e7c2014-08-26 15:23:08 -0700184 }
185
186 @Override
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700187 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
alshabibf1216ed2014-09-03 11:53:54 -0700188 switch (newRole) {
tom782a7cf2014-09-11 23:58:38 -0700189 case MASTER:
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700190 controller.setRole(dpid(deviceId.uri()), RoleState.MASTER);
tom782a7cf2014-09-11 23:58:38 -0700191 break;
192 case STANDBY:
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700193 controller.setRole(dpid(deviceId.uri()), RoleState.EQUAL);
tom782a7cf2014-09-11 23:58:38 -0700194 break;
195 case NONE:
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700196 controller.setRole(dpid(deviceId.uri()), RoleState.SLAVE);
tom782a7cf2014-09-11 23:58:38 -0700197 break;
198 default:
199 LOG.error("Unknown Mastership state : {}", newRole);
alshabibf1216ed2014-09-03 11:53:54 -0700200
201 }
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700202 LOG.info("Accepting mastership role change for device {}", deviceId);
tomab21e7c2014-08-26 15:23:08 -0700203 }
204
sangho538108b2015-04-08 14:29:20 -0700205 private void pushPortMetrics(Dpid dpid, OFPortStatsReply msg) {
206 DeviceId deviceId = DeviceId.deviceId(dpid.uri(dpid));
207
208 Collection<PortStatistics> stats = buildPortStatistics(deviceId, msg);
209
210 providerService.updatePortStatistics(deviceId, stats);
211 }
212
213 private Collection<PortStatistics> buildPortStatistics(DeviceId deviceId, OFPortStatsReply msg) {
214
215 HashSet<PortStatistics> stats = Sets.newHashSet();
216
217 for (OFPortStatsEntry entry: msg.getEntries()) {
218 if (entry.getPortNo().getPortNumber() < 0) {
219 continue;
220 }
221 DefaultPortStatistics.Builder builder = DefaultPortStatistics.builder();
222 DefaultPortStatistics stat = builder.setDeviceId(deviceId)
223 .setPort(entry.getPortNo().getPortNumber())
224 .setPacketsReceived(entry.getRxPackets().getValue())
225 .setPacketsSent(entry.getTxPackets().getValue())
226 .setBytesReceived(entry.getRxBytes().getValue())
227 .setBytesSent(entry.getTxBytes().getValue())
228 .setPacketsRxDropped(entry.getRxDropped().getValue())
229 .setPacketsTxDropped(entry.getTxDropped().getValue())
230 .setPacketsRxErrors(entry.getRxErrors().getValue())
231 .setPacketsTxErrors(entry.getTxErrors().getValue())
232 .setDurationSec(entry.getDurationSec())
233 .setDurationNano(entry.getDurationNsec())
234 .build();
235
236 stats.add(stat);
237 }
238
239 return Collections.unmodifiableSet(stats);
240
241 }
242
243 private class InternalDeviceProvider implements OpenFlowSwitchListener, OpenFlowEventListener {
alshabibf1216ed2014-09-03 11:53:54 -0700244 @Override
tomd1900f32014-09-03 14:08:16 -0700245 public void switchAdded(Dpid dpid) {
alshabib6f5460b2014-09-03 14:46:17 -0700246 if (providerService == null) {
247 return;
248 }
tom782a7cf2014-09-11 23:58:38 -0700249 DeviceId did = deviceId(uri(dpid));
alshabib6f5460b2014-09-03 14:46:17 -0700250 OpenFlowSwitch sw = controller.getSwitch(dpid);
251
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700252 Device.Type deviceType = sw.isOptical() ? Device.Type.ROADM :
253 Device.Type.SWITCH;
alshabib7911a052014-10-16 17:49:37 -0700254 ChassisId cId = new ChassisId(dpid.value());
Ray Milkeye53f1712015-01-16 09:17:16 -0800255
Thomas Vachuska82041f52014-11-30 22:14:02 -0800256 SparseAnnotations annotations = DefaultAnnotations.builder()
Ray Milkeye53f1712015-01-16 09:17:16 -0800257 .set("protocol", sw.factory().getVersion().toString())
258 .set("channelId", sw.channelId())
259 .build();
260
tomd1900f32014-09-03 14:08:16 -0700261 DeviceDescription description =
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700262 new DefaultDeviceDescription(did.uri(), deviceType,
Ray Milkeyd3edd032015-01-16 11:38:58 -0800263 sw.manufacturerDescription(),
tom782a7cf2014-09-11 23:58:38 -0700264 sw.hardwareDescription(),
265 sw.softwareDescription(),
alshabib7911a052014-10-16 17:49:37 -0700266 sw.serialNumber(),
Thomas Vachuska82041f52014-11-30 22:14:02 -0800267 cId, annotations);
tom782a7cf2014-09-11 23:58:38 -0700268 providerService.deviceConnected(did, description);
Ayaka Koshibe5460d622015-05-14 12:19:19 -0700269 providerService.updatePorts(did, buildPortDescriptions(sw));
sangho538108b2015-04-08 14:29:20 -0700270
Thomas Vachuskafc52fec2015-05-18 19:13:56 -0700271 PortStatsCollector psc =
272 new PortStatsCollector(controller.getSwitch(dpid), POLL_INTERVAL);
sangho538108b2015-04-08 14:29:20 -0700273 psc.start();
274 collectors.put(dpid, psc);
alshabib25c8eec2014-09-04 16:41:31 -0700275 }
276
alshabibf1216ed2014-09-03 11:53:54 -0700277 @Override
278 public void switchRemoved(Dpid dpid) {
alshabib6f5460b2014-09-03 14:46:17 -0700279 if (providerService == null) {
280 return;
281 }
tom782a7cf2014-09-11 23:58:38 -0700282 providerService.deviceDisconnected(deviceId(uri(dpid)));
alshabibf1216ed2014-09-03 11:53:54 -0700283
sangho538108b2015-04-08 14:29:20 -0700284 PortStatsCollector collector = collectors.remove(dpid);
285 if (collector != null) {
286 collector.stop();
287 }
288 }
Ayaka Koshibe38594c22014-10-22 13:36:12 -0700289
290 @Override
291 public void switchChanged(Dpid dpid) {
292 if (providerService == null) {
293 return;
294 }
295 DeviceId did = deviceId(uri(dpid));
296 OpenFlowSwitch sw = controller.getSwitch(dpid);
Ayaka Koshibe5460d622015-05-14 12:19:19 -0700297 providerService.updatePorts(did, buildPortDescriptions(sw));
Ayaka Koshibe38594c22014-10-22 13:36:12 -0700298 }
299
alshabiba14f3642014-09-05 09:31:31 -0700300 @Override
301 public void portChanged(Dpid dpid, OFPortStatus status) {
alshabibafc514a2014-12-01 14:44:05 -0800302 PortDescription portDescription = buildPortDescription(status);
tom782a7cf2014-09-11 23:58:38 -0700303 providerService.portStatusChanged(deviceId(uri(dpid)), portDescription);
alshabibf1216ed2014-09-03 11:53:54 -0700304 }
305
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700306 @Override
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700307 public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) {
308 MastershipRole request = roleOf(requested);
309 MastershipRole reply = roleOf(response);
310
311 providerService.receivedRoleReply(deviceId(uri(dpid)), request, reply);
312 }
313
314 /**
315 * Translates a RoleState to the corresponding MastershipRole.
316 *
Thomas Vachuskafc52fec2015-05-18 19:13:56 -0700317 * @param response role state
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700318 * @return a MastershipRole
319 */
320 private MastershipRole roleOf(RoleState response) {
321 switch (response) {
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700322 case MASTER:
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700323 return MastershipRole.MASTER;
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700324 case EQUAL:
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700325 return MastershipRole.STANDBY;
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700326 case SLAVE:
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700327 return MastershipRole.NONE;
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700328 default:
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700329 LOG.warn("unknown role {}", response);
330 return null;
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700331 }
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700332 }
333
alshabiba14f3642014-09-05 09:31:31 -0700334 /**
335 * Builds a list of port descriptions for a given list of ports.
tomff7eb7c2014-09-08 12:49:03 -0700336 *
alshabiba14f3642014-09-05 09:31:31 -0700337 * @return list of portdescriptions
338 */
Ayaka Koshibe5460d622015-05-14 12:19:19 -0700339 private List<PortDescription> buildPortDescriptions(OpenFlowSwitch sw) {
340 final List<PortDescription> portDescs = new ArrayList<>(sw.getPorts().size());
341 sw.getPorts().forEach(port -> portDescs.add(buildPortDescription(port)));
342 if (sw.isOptical()) {
343 OpenFlowOpticalSwitch opsw = (OpenFlowOpticalSwitch) sw;
344 opsw.getPortTypes().forEach(type -> {
Ayaka Koshibe5460d622015-05-14 12:19:19 -0700345 opsw.getPortsOf(type).forEach(
346 op -> {
347 portDescs.add(buildPortDescription(type, (OFPortOptical) op));
348 }
349 );
350 });
alshabib4680bb62014-09-04 17:15:08 -0700351 }
352 return portDescs;
353 }
354
alshabiba14f3642014-09-05 09:31:31 -0700355 /**
Ray Milkeye0fade72015-01-15 13:29:47 -0800356 * Creates an annotation for the port name if one is available.
357 *
358 * @param port description of the port
359 * @return annotation containing the port name if one is found,
360 * null otherwise
361 */
Ayaka Koshibe5460d622015-05-14 12:19:19 -0700362 private SparseAnnotations makePortNameAnnotation(String port) {
Ray Milkeye0fade72015-01-15 13:29:47 -0800363 SparseAnnotations annotations = null;
Ayaka Koshibe5460d622015-05-14 12:19:19 -0700364 String portName = Strings.emptyToNull(port);
Ray Milkeye0fade72015-01-15 13:29:47 -0800365 if (portName != null) {
366 annotations = DefaultAnnotations.builder()
Thomas Vachuskab52a0142015-04-21 17:48:15 -0700367 .set(AnnotationKeys.PORT_NAME, portName).build();
Ray Milkeye0fade72015-01-15 13:29:47 -0800368 }
369 return annotations;
370 }
371
372 /**
Ayaka Koshibe5460d622015-05-14 12:19:19 -0700373 * Build a portDescription from a given Ethernet port description.
tomff7eb7c2014-09-08 12:49:03 -0700374 *
alshabiba14f3642014-09-05 09:31:31 -0700375 * @param port the port to build from.
376 * @return portDescription for the port.
377 */
378 private PortDescription buildPortDescription(OFPortDesc port) {
Thomas Vachuskad16ce182014-10-29 17:25:29 -0700379 PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());
380 boolean enabled =
381 !port.getState().contains(OFPortState.LINK_DOWN) &&
382 !port.getConfig().contains(OFPortConfig.PORT_DOWN);
383 Port.Type type = port.getCurr().contains(OFPortFeatures.PF_FIBER) ? FIBER : COPPER;
Ayaka Koshibe5460d622015-05-14 12:19:19 -0700384 SparseAnnotations annotations = makePortNameAnnotation(port.getName());
Ray Milkeye0fade72015-01-15 13:29:47 -0800385 return new DefaultPortDescription(portNo, enabled, type,
386 portSpeed(port), annotations);
alshabiba14f3642014-09-05 09:31:31 -0700387 }
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700388
Ayaka Koshibe5460d622015-05-14 12:19:19 -0700389 /**
390 * Build a portDescription from a given a port description describing some
391 * Optical port.
392 *
393 * @param port description property type.
394 * @param port the port to build from.
395 * @return portDescription for the port.
396 */
397 private PortDescription buildPortDescription(PortDescPropertyType ptype, OFPortOptical port) {
398 // Minimally functional fixture. This needs to be fixed as we add better support.
399 PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());
Ayaka Koshibe74b55272015-05-28 15:16:04 -0700400
Ayaka Koshibe5460d622015-05-14 12:19:19 -0700401 boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN)
402 && !port.getConfig().contains(OFPortConfig.PORT_DOWN);
403 SparseAnnotations annotations = makePortNameAnnotation(port.getName());
Ayaka Koshibe5460d622015-05-14 12:19:19 -0700404
405 if (port.getVersion() == OFVersion.OF_13
406 && ptype == PortDescPropertyType.OPTICAL_TRANSPORT) {
407 // At this point, not much is carried in the optical port message.
Ayaka Koshibeae541732015-05-19 13:37:27 -0700408 LOG.debug("Optical transport port message {}", port.toString());
Ayaka Koshibe5460d622015-05-14 12:19:19 -0700409 } else {
410 // removable once 1.4+ support complete.
Ayaka Koshibeae541732015-05-19 13:37:27 -0700411 LOG.debug("Unsupported optical port properties");
Ayaka Koshibe5460d622015-05-14 12:19:19 -0700412 }
Ayaka Koshibe74b55272015-05-28 15:16:04 -0700413 return new DefaultPortDescription(portNo, enabled, FIBER, 0, annotations);
Ayaka Koshibe5460d622015-05-14 12:19:19 -0700414 }
415
alshabibafc514a2014-12-01 14:44:05 -0800416 private PortDescription buildPortDescription(OFPortStatus status) {
417 OFPortDesc port = status.getDesc();
418 if (status.getReason() != OFPortReason.DELETE) {
419 return buildPortDescription(port);
420 } else {
421 PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());
422 Port.Type type = port.getCurr().contains(OFPortFeatures.PF_FIBER) ? FIBER : COPPER;
Ayaka Koshibe5460d622015-05-14 12:19:19 -0700423 SparseAnnotations annotations = makePortNameAnnotation(port.getName());
Ray Milkeye0fade72015-01-15 13:29:47 -0800424 return new DefaultPortDescription(portNo, false, type,
425 portSpeed(port), annotations);
alshabibafc514a2014-12-01 14:44:05 -0800426 }
427 }
428
Thomas Vachuskad16ce182014-10-29 17:25:29 -0700429 private long portSpeed(OFPortDesc port) {
430 if (port.getVersion() == OFVersion.OF_13) {
431 return port.getCurrSpeed() / MBPS;
432 }
433
434 PortSpeed portSpeed = PortSpeed.SPEED_NONE;
435 for (OFPortFeatures feat : port.getCurr()) {
436 portSpeed = PortSpeed.max(portSpeed, feat.getPortSpeed());
437 }
Thomas Vachuska98eda532014-10-29 17:31:02 -0700438 return portSpeed.getSpeedBps() / MBPS;
Thomas Vachuskad16ce182014-10-29 17:25:29 -0700439 }
sangho538108b2015-04-08 14:29:20 -0700440
441 @Override
442 public void handleMessage(Dpid dpid, OFMessage msg) {
443 switch (msg.getType()) {
444 case STATS_REPLY:
445 if (((OFStatsReply) msg).getStatsType() == OFStatsType.PORT) {
446 pushPortMetrics(dpid, (OFPortStatsReply) msg);
447 }
448 break;
449 default:
450 break;
451 }
452 }
alshabibf1216ed2014-09-03 11:53:54 -0700453 }
454
tomb5a46e62014-08-26 14:20:00 -0700455}