2 * Copyright 2014-2015 Open Networking Laboratory
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org.onosproject.provider.of.device.impl;
18 import static com.google.common.base.Preconditions.checkArgument;
19 import static com.google.common.base.Strings.isNullOrEmpty;
20 import static org.onlab.util.Tools.get;
21 import static org.onosproject.net.DeviceId.deviceId;
22 import static org.onosproject.net.Port.Type.COPPER;
23 import static org.onosproject.net.Port.Type.FIBER;
24 import static org.onosproject.openflow.controller.Dpid.dpid;
25 import static org.onosproject.openflow.controller.Dpid.uri;
26 import static org.slf4j.LoggerFactory.getLogger;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Dictionary;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.List;
36 import org.apache.felix.scr.annotations.Activate;
37 import org.apache.felix.scr.annotations.Component;
38 import org.apache.felix.scr.annotations.Deactivate;
39 import org.apache.felix.scr.annotations.Modified;
40 import org.apache.felix.scr.annotations.Property;
41 import org.apache.felix.scr.annotations.Reference;
42 import org.apache.felix.scr.annotations.ReferenceCardinality;
43 import org.onlab.packet.ChassisId;
44 import org.onlab.util.Frequency;
45 import org.onlab.util.Spectrum;
46 import org.onosproject.cfg.ComponentConfigService;
47 import org.onosproject.net.AnnotationKeys;
48 import org.onosproject.net.ChannelSpacing;
49 import org.onosproject.net.DefaultAnnotations;
50 import org.onosproject.net.Device;
51 import org.onosproject.net.DeviceId;
52 import org.onosproject.net.GridType;
53 import org.onosproject.net.MastershipRole;
54 import org.onosproject.net.OchSignal;
55 import org.onosproject.net.OduCltPort;
56 import org.onosproject.net.OduSignalType;
57 import org.onosproject.net.Port;
58 import org.onosproject.net.PortNumber;
59 import org.onosproject.net.SparseAnnotations;
60 import org.onosproject.net.device.DefaultDeviceDescription;
61 import org.onosproject.net.device.DefaultPortDescription;
62 import org.onosproject.net.device.DefaultPortStatistics;
63 import org.onosproject.net.device.DeviceDescription;
64 import org.onosproject.net.device.DeviceProvider;
65 import org.onosproject.net.device.DeviceProviderRegistry;
66 import org.onosproject.net.device.DeviceProviderService;
67 import org.onosproject.net.device.OchPortDescription;
68 import org.onosproject.net.device.OduCltPortDescription;
69 import org.onosproject.net.device.OmsPortDescription;
70 import org.onosproject.net.device.PortDescription;
71 import org.onosproject.net.device.PortStatistics;
72 import org.onosproject.net.provider.AbstractProvider;
73 import org.onosproject.net.provider.ProviderId;
74 import org.onosproject.openflow.controller.Dpid;
75 import org.onosproject.openflow.controller.OpenFlowController;
76 import org.onosproject.openflow.controller.OpenFlowEventListener;
77 import org.onosproject.openflow.controller.OpenFlowOpticalSwitch;
78 import org.onosproject.openflow.controller.OpenFlowSwitch;
79 import org.onosproject.openflow.controller.OpenFlowSwitchListener;
80 import org.onosproject.openflow.controller.PortDescPropertyType;
81 import org.onosproject.openflow.controller.RoleState;
82 import org.osgi.service.component.ComponentContext;
83 import org.projectfloodlight.openflow.protocol.OFCalientPortDescStatsEntry;
84 import org.projectfloodlight.openflow.protocol.OFExpPort;
85 import org.projectfloodlight.openflow.protocol.OFExpPortDescPropOpticalTransport;
86 import org.projectfloodlight.openflow.protocol.OFExpPortOpticalTransportLayerEntry;
87 import org.projectfloodlight.openflow.protocol.OFFactory;
88 import org.projectfloodlight.openflow.protocol.OFMessage;
89 import org.projectfloodlight.openflow.protocol.OFObject;
90 import org.projectfloodlight.openflow.protocol.OFPortConfig;
91 import org.projectfloodlight.openflow.protocol.OFPortDesc;
92 import org.projectfloodlight.openflow.protocol.OFPortDescPropOpticalTransport;
93 import org.projectfloodlight.openflow.protocol.OFPortFeatures;
94 import org.projectfloodlight.openflow.protocol.OFPortOptical;
95 import org.projectfloodlight.openflow.protocol.OFPortOpticalTransportLayerClass;
96 import org.projectfloodlight.openflow.protocol.OFPortOpticalTransportSignalType;
97 import org.projectfloodlight.openflow.protocol.OFPortReason;
98 import org.projectfloodlight.openflow.protocol.OFPortState;
99 import org.projectfloodlight.openflow.protocol.OFPortStatsEntry;
100 import org.projectfloodlight.openflow.protocol.OFPortStatsReply;
101 import org.projectfloodlight.openflow.protocol.OFPortStatus;
102 import org.projectfloodlight.openflow.protocol.OFStatsReply;
103 import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
104 import org.projectfloodlight.openflow.protocol.OFStatsType;
105 import org.projectfloodlight.openflow.protocol.OFVersion;
106 import org.projectfloodlight.openflow.types.PortSpeed;
107 import org.slf4j.Logger;
109 import com.google.common.base.Strings;
110 import com.google.common.collect.Lists;
111 import com.google.common.collect.Maps;
112 import com.google.common.collect.Sets;
115 * Provider which uses an OpenFlow controller to detect network
116 * infrastructure devices.
118 @Component(immediate = true)
119 public class OpenFlowDeviceProvider extends AbstractProvider implements DeviceProvider {
121 private static final Logger LOG = getLogger(OpenFlowDeviceProvider.class);
123 private static final long MBPS = 1_000 * 1_000;
124 private static final Frequency FREQ100 = Frequency.ofGHz(100);
125 private static final Frequency FREQ193_1 = Frequency.ofTHz(193.1);
126 private static final Frequency FREQ4_4 = Frequency.ofTHz(4.4);
128 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
129 protected DeviceProviderRegistry providerRegistry;
131 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
132 protected OpenFlowController controller;
134 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
135 protected ComponentConfigService cfgService;
137 private DeviceProviderService providerService;
139 private final InternalDeviceProvider listener = new InternalDeviceProvider();
141 // TODO: We need to make the poll interval configurable.
142 static final int POLL_INTERVAL = 5;
143 @Property(name = "PortStatsPollFrequency", intValue = POLL_INTERVAL,
144 label = "Frequency (in seconds) for polling switch Port statistics")
145 private int portStatsPollFrequency = POLL_INTERVAL;
147 private HashMap<Dpid, PortStatsCollector> collectors = Maps.newHashMap();
150 * Creates an OpenFlow device provider.
152 public OpenFlowDeviceProvider() {
153 super(new ProviderId("of", "org.onosproject.provider.openflow"));
157 public void activate(ComponentContext context) {
158 cfgService.registerProperties(getClass());
159 providerService = providerRegistry.register(this);
160 controller.addListener(listener);
161 controller.addEventListener(listener);
162 connectInitialDevices();
167 public void deactivate(ComponentContext context) {
168 cfgService.unregisterProperties(getClass(), false);
169 controller.removeListener(listener);
171 providerRegistry.unregister(this);
172 collectors.values().forEach(PortStatsCollector::stop);
173 providerService = null;
178 public void modified(ComponentContext context) {
179 Dictionary<?, ?> properties = context.getProperties();
180 int newPortStatsPollFrequency;
182 String s = get(properties, "PortStatsPollFrequency");
183 newPortStatsPollFrequency = isNullOrEmpty(s) ? portStatsPollFrequency : Integer.parseInt(s.trim());
185 } catch (NumberFormatException | ClassCastException e) {
186 newPortStatsPollFrequency = portStatsPollFrequency;
189 if (newPortStatsPollFrequency != portStatsPollFrequency) {
190 portStatsPollFrequency = newPortStatsPollFrequency;
191 collectors.values().forEach(psc -> psc.adjustPollInterval(portStatsPollFrequency));
194 LOG.info("Settings: portStatsPollFrequency={}", portStatsPollFrequency);
197 private void connectInitialDevices() {
198 for (OpenFlowSwitch sw : controller.getSwitches()) {
200 listener.switchAdded(new Dpid(sw.getId()));
201 } catch (Exception e) {
202 LOG.warn("Failed initially adding {} : {}", sw.getStringId(), e.getMessage());
203 LOG.debug("Error details:", e);
204 // disconnect to trigger switch-add later
205 sw.disconnectSwitch();
207 PortStatsCollector psc = new PortStatsCollector(sw, portStatsPollFrequency);
209 collectors.put(new Dpid(sw.getId()), psc);
213 private void disconnectDevices() {
214 // Only disconnect the devices for which we are currently master.
215 controller.getMasterSwitches().forEach(sw -> listener.switchRemoved(new Dpid(sw.getId())));
219 public boolean isReachable(DeviceId deviceId) {
220 OpenFlowSwitch sw = controller.getSwitch(dpid(deviceId.uri()));
221 return sw != null && sw.isConnected();
225 public void triggerProbe(DeviceId deviceId) {
226 LOG.debug("Triggering probe on device {}", deviceId);
228 final Dpid dpid = dpid(deviceId.uri());
229 OpenFlowSwitch sw = controller.getSwitch(dpid);
230 if (sw == null || !sw.isConnected()) {
231 LOG.error("Failed to probe device {} on sw={}", deviceId, sw);
232 providerService.deviceDisconnected(deviceId);
235 LOG.trace("Confirmed device {} connection", deviceId);
238 // Prompt an update of port information. We can use any XID for this.
239 OFFactory fact = sw.factory();
240 switch (fact.getVersion()) {
242 sw.sendMsg(fact.buildFeaturesRequest().setXid(0).build());
245 sw.sendMsg(fact.buildPortDescStatsRequest().setXid(0).build());
248 LOG.warn("Unhandled protocol version");
253 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
256 controller.setRole(dpid(deviceId.uri()), RoleState.MASTER);
259 controller.setRole(dpid(deviceId.uri()), RoleState.EQUAL);
262 controller.setRole(dpid(deviceId.uri()), RoleState.SLAVE);
265 LOG.error("Unknown Mastership state : {}", newRole);
268 LOG.debug("Accepting mastership role change for device {}", deviceId);
271 private void pushPortMetrics(Dpid dpid, List<OFPortStatsEntry> portStatsEntries) {
272 DeviceId deviceId = DeviceId.deviceId(dpid.uri(dpid));
273 Collection<PortStatistics> stats = buildPortStatistics(deviceId, portStatsEntries);
274 providerService.updatePortStatistics(deviceId, stats);
277 private Collection<PortStatistics> buildPortStatistics(DeviceId deviceId,
278 List<OFPortStatsEntry> entries) {
279 HashSet<PortStatistics> stats = Sets.newHashSet();
281 for (OFPortStatsEntry entry : entries) {
283 if (entry == null || entry.getPortNo() == null || entry.getPortNo().getPortNumber() < 0) {
286 DefaultPortStatistics.Builder builder = DefaultPortStatistics.builder();
287 DefaultPortStatistics stat = builder.setDeviceId(deviceId)
288 .setPort(entry.getPortNo().getPortNumber())
289 .setPacketsReceived(entry.getRxPackets().getValue())
290 .setPacketsSent(entry.getTxPackets().getValue())
291 .setBytesReceived(entry.getRxBytes().getValue())
292 .setBytesSent(entry.getTxBytes().getValue())
293 .setPacketsRxDropped(entry.getRxDropped().getValue())
294 .setPacketsTxDropped(entry.getTxDropped().getValue())
295 .setPacketsRxErrors(entry.getRxErrors().getValue())
296 .setPacketsTxErrors(entry.getTxErrors().getValue())
297 .setDurationSec(entry.getVersion() == OFVersion.OF_10 ? 0 : entry.getDurationSec())
298 .setDurationNano(entry.getVersion() == OFVersion.OF_10 ? 0 : entry.getDurationNsec())
302 } catch (Exception e) {
303 LOG.warn("Unable to process port stats", e);
307 return Collections.unmodifiableSet(stats);
311 private class InternalDeviceProvider implements OpenFlowSwitchListener, OpenFlowEventListener {
313 private HashMap<Dpid, List<OFPortStatsEntry>> portStatsReplies = new HashMap<>();
316 public void switchAdded(Dpid dpid) {
317 if (providerService == null) {
320 DeviceId did = deviceId(uri(dpid));
321 OpenFlowSwitch sw = controller.getSwitch(dpid);
326 ChassisId cId = new ChassisId(dpid.value());
328 SparseAnnotations annotations = DefaultAnnotations.builder()
329 .set(AnnotationKeys.PROTOCOL, sw.factory().getVersion().toString())
330 .set(AnnotationKeys.CHANNEL_ID, sw.channelId())
331 .set(AnnotationKeys.MANAGEMENT_ADDRESS, sw.channelId().split(":")[0])
334 DeviceDescription description =
335 new DefaultDeviceDescription(did.uri(), sw.deviceType(),
336 sw.manufacturerDescription(),
337 sw.hardwareDescription(),
338 sw.softwareDescription(),
341 providerService.deviceConnected(did, description);
342 providerService.updatePorts(did, buildPortDescriptions(sw));
344 PortStatsCollector psc =
345 new PortStatsCollector(sw, portStatsPollFrequency);
347 collectors.put(dpid, psc);
349 //figure out race condition for collectors.remove() and collectors.put()
350 if (controller.getSwitch(dpid) == null) {
356 public void switchRemoved(Dpid dpid) {
357 if (providerService == null) {
360 providerService.deviceDisconnected(deviceId(uri(dpid)));
362 PortStatsCollector collector = collectors.remove(dpid);
363 if (collector != null) {
369 public void switchChanged(Dpid dpid) {
370 if (providerService == null) {
373 DeviceId did = deviceId(uri(dpid));
374 OpenFlowSwitch sw = controller.getSwitch(dpid);
378 providerService.updatePorts(did, buildPortDescriptions(sw));
382 public void portChanged(Dpid dpid, OFPortStatus status) {
383 PortDescription portDescription = buildPortDescription(status);
384 providerService.portStatusChanged(deviceId(uri(dpid)), portDescription);
388 public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) {
389 MastershipRole request = roleOf(requested);
390 MastershipRole reply = roleOf(response);
391 providerService.receivedRoleReply(deviceId(uri(dpid)), request, reply);
395 * Translates a RoleState to the corresponding MastershipRole.
397 * @param response role state
398 * @return a MastershipRole
400 private MastershipRole roleOf(RoleState response) {
403 return MastershipRole.MASTER;
405 return MastershipRole.STANDBY;
407 return MastershipRole.NONE;
409 LOG.warn("unknown role {}", response);
415 * Builds a list of port descriptions for a given list of ports.
417 * @return list of portdescriptions
419 private List<PortDescription> buildPortDescriptions(OpenFlowSwitch sw) {
420 final List<PortDescription> portDescs = new ArrayList<>(sw.getPorts().size());
421 if (!(Device.Type.ROADM.equals(sw.deviceType()))) {
422 sw.getPorts().forEach(port -> portDescs.add(buildPortDescription(port)));
425 OpenFlowOpticalSwitch opsw;
426 switch (sw.deviceType()) {
428 opsw = (OpenFlowOpticalSwitch) sw;
429 List<OFPortDesc> ports = opsw.getPorts();
430 LOG.debug("SW ID {} , ETH- ODU CLT Ports {}", opsw.getId(), ports);
431 // ODU client ports are reported as ETH
432 ports.forEach(port -> portDescs.add(buildOduCltPortDescription(port)));
434 opsw.getPortTypes().forEach(type -> {
435 List<? extends OFObject> portsOf = opsw.getPortsOf(type);
436 LOG.debug("Ports Of{}", portsOf);
439 portDescs.add(buildPortDescription(type, (OFObject) op));
445 opsw = (OpenFlowOpticalSwitch) sw;
446 opsw.getPortTypes().forEach(type -> {
447 opsw.getPortsOf(type).forEach(
449 portDescs.add(buildPortDescription((OFCalientPortDescStatsEntry) op));
461 private PortDescription buildOduCltPortDescription(OFPortDesc port) {
462 PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());
463 boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN) &&
464 !port.getConfig().contains(OFPortConfig.PORT_DOWN);
465 Long portSpeed = portSpeed(port);
466 OduCltPort.SignalType sigType = null;
468 switch (portSpeed.toString()) {
470 sigType = OduCltPort.SignalType.CLT_1GBE;
473 sigType = OduCltPort.SignalType.CLT_10GBE;
476 sigType = OduCltPort.SignalType.CLT_40GBE;
479 sigType = OduCltPort.SignalType.CLT_100GBE;
482 throw new RuntimeException("Un recognize OduClt speed: " + portSpeed.toString());
485 SparseAnnotations annotations = buildOduCltAnnotation(port);
486 return new OduCltPortDescription(portNo, enabled, sigType, annotations);
489 private SparseAnnotations buildOduCltAnnotation(OFPortDesc port) {
490 SparseAnnotations annotations = null;
491 String portName = Strings.emptyToNull(port.getName());
492 if (portName != null) {
493 annotations = DefaultAnnotations.builder()
494 .set(AnnotationKeys.PORT_NAME, portName)
495 .set(AnnotationKeys.STATIC_PORT, Boolean.TRUE.toString()).build();
500 private PortDescription buildPortDescription(PortDescPropertyType ptype, OFObject port) {
501 if (port instanceof OFPortOptical) {
502 return buildPortDescription(ptype, (OFPortOptical) port);
504 return buildPortDescription(ptype, (OFExpPort) port);
508 * Build a portDescription from a given a port description describing some
511 * @param ptype description property type.
512 * @param port the port to build from.
513 * @return portDescription for the port.
515 private PortDescription buildPortDescription(PortDescPropertyType ptype, OFExpPort port) {
516 PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());
517 boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN)
518 && !port.getConfig().contains(OFPortConfig.PORT_DOWN);
519 SparseAnnotations annotations = makePortNameAnnotation(port.getName());
521 OFExpPortDescPropOpticalTransport firstProp = port.getProperties().get(0);
522 OFPortOpticalTransportSignalType sigType = firstProp.getPortSignalType();
524 DefaultPortDescription portDes = null;
527 portDes = new OmsPortDescription(portNo, enabled, FREQ193_1, FREQ193_1.add(FREQ4_4),
528 FREQ100, annotations);
531 OFExpPortOpticalTransportLayerEntry entry = firstProp.getFeatures().get(0).getValue().get(0);
532 OFPortOpticalTransportLayerClass layerClass = entry.getLayerClass();
533 if (!OFPortOpticalTransportLayerClass.ODU.equals(layerClass)) {
534 LOG.error("Unsupported layer Class {} ", layerClass);
538 // convert to ONOS OduSignalType
539 OduSignalType oduSignalType = OpenFlowDeviceValueMapper.
540 lookupOduSignalType((byte) entry.getSignalType());
541 //OchSignal is needed for OchPortDescription constructor,
542 //yet not relevant for tunable OCH port, creating with default parameters
543 OchSignal signalId = new OchSignal(GridType.DWDM, ChannelSpacing.CHL_50GHZ, 1, 1);
545 portDes = new OchPortDescription(portNo, enabled,
546 oduSignalType, true, signalId, annotations);
551 LOG.error("Signal tpye OTU2/4 not supported yet ", port.toString());
561 * Creates an annotation for the port name if one is available.
563 * @param port description of the port
564 * @return annotation containing the port name if one is found,
567 private SparseAnnotations makePortNameAnnotation(String port) {
568 SparseAnnotations annotations = null;
569 String portName = Strings.emptyToNull(port);
570 if (portName != null) {
571 annotations = DefaultAnnotations.builder()
572 .set(AnnotationKeys.PORT_NAME, portName).build();
578 * Build a portDescription from a given Ethernet port description.
580 * @param port the port to build from.
581 * @return portDescription for the port.
583 private PortDescription buildPortDescription(OFPortDesc port) {
584 PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());
586 !port.getState().contains(OFPortState.LINK_DOWN) &&
587 !port.getConfig().contains(OFPortConfig.PORT_DOWN);
588 Port.Type type = port.getCurr().contains(OFPortFeatures.PF_FIBER) ? FIBER : COPPER;
589 SparseAnnotations annotations = makePortNameAnnotation(port.getName());
590 return new DefaultPortDescription(portNo, enabled, type,
591 portSpeed(port), annotations);
595 * Build a portDescription from a given a port description describing some
598 * @param port description property type.
599 * @param port the port to build from.
600 * @return portDescription for the port.
602 private PortDescription buildPortDescription(PortDescPropertyType ptype, OFPortOptical port) {
603 checkArgument(port.getDesc().size() >= 1);
605 // Minimally functional fixture. This needs to be fixed as we add better support.
606 PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());
608 boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN)
609 && !port.getConfig().contains(OFPortConfig.PORT_DOWN);
610 SparseAnnotations annotations = makePortNameAnnotation(port.getName());
612 if (port.getVersion() == OFVersion.OF_13
613 && ptype == PortDescPropertyType.OPTICAL_TRANSPORT) {
614 // At this point, not much is carried in the optical port message.
615 LOG.debug("Optical transport port message {}", port.toString());
617 // removable once 1.4+ support complete.
618 LOG.debug("Unsupported optical port properties");
621 OFPortDescPropOpticalTransport desc = port.getDesc().get(0);
622 switch (desc.getPortSignalType()) {
623 // FIXME: use constants once loxi has full optical extensions
625 // Assume complete optical spectrum and 50 GHz grid
626 // LINC-OE is only supported optical OF device for now
627 return new OmsPortDescription(portNo, enabled,
628 Spectrum.U_BAND_MIN, Spectrum.O_BAND_MAX, Frequency.ofGHz(50), annotations);
630 OchSignal signal = new OchSignal(GridType.DWDM, ChannelSpacing.CHL_50GHZ, 0, 4);
631 return new OchPortDescription(portNo, enabled, OduSignalType.ODU4,
632 true, signal, annotations);
637 return new DefaultPortDescription(portNo, enabled, FIBER, 0, annotations);
641 * Build a portDescription from a given port description describing a fiber switch optical port.
643 * @param port description property type.
644 * @param port the port to build from.
645 * @return portDescription for the port.
647 private PortDescription buildPortDescription(OFCalientPortDescStatsEntry port) {
648 PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());
650 // FIXME when Calient OF agent reports port status
651 boolean enabled = true;
652 SparseAnnotations annotations = makePortNameAnnotation(port.getName());
655 // Wavelength range: 1260 - 1630 nm, grid is irrelevant for this type of switch
656 return new OmsPortDescription(portNo, enabled,
657 Spectrum.U_BAND_MIN, Spectrum.O_BAND_MAX, Frequency.ofGHz(100), annotations);
660 private PortDescription buildPortDescription(OFPortStatus status) {
661 OFPortDesc port = status.getDesc();
662 if (status.getReason() != OFPortReason.DELETE) {
663 return buildPortDescription(port);
665 PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());
666 Port.Type type = port.getCurr().contains(OFPortFeatures.PF_FIBER) ? FIBER : COPPER;
667 SparseAnnotations annotations = makePortNameAnnotation(port.getName());
668 return new DefaultPortDescription(portNo, false, type,
669 portSpeed(port), annotations);
673 private long portSpeed(OFPortDesc port) {
674 if (port.getVersion() == OFVersion.OF_13) {
675 return port.getCurrSpeed() / MBPS;
678 PortSpeed portSpeed = PortSpeed.SPEED_NONE;
679 for (OFPortFeatures feat : port.getCurr()) {
680 portSpeed = PortSpeed.max(portSpeed, feat.getPortSpeed());
682 return portSpeed.getSpeedBps() / MBPS;
686 public void handleMessage(Dpid dpid, OFMessage msg) {
687 switch (msg.getType()) {
689 if (((OFStatsReply) msg).getStatsType() == OFStatsType.PORT) {
690 OFPortStatsReply portStatsReply = (OFPortStatsReply) msg;
691 List<OFPortStatsEntry> portStatsReplyList = portStatsReplies.get(dpid);
692 if (portStatsReplyList == null) {
693 portStatsReplyList = Lists.newArrayList();
695 portStatsReplyList.addAll(portStatsReply.getEntries());
696 portStatsReplies.put(dpid, portStatsReplyList);
697 if (!portStatsReply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
698 pushPortMetrics(dpid, portStatsReplies.get(dpid));
699 portStatsReplies.get(dpid).clear();