Committed by
Gerrit Code Review
ONOS-1440: Implements port statistics feature, which polls port statistics of al…
…l devices every 10 seconds. Also, implemented a simple portstats ONOS CLI command to show the statistics. Change-Id: I57e046ae2c2463a58b478d3a5b523422cde71ba2
Showing
16 changed files
with
837 additions
and
4 deletions
1 | +package org.onosproject.cli.net; | ||
2 | + | ||
3 | +/* | ||
4 | + * Copyright 2015 Open Networking Laboratory | ||
5 | + * | ||
6 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
7 | + * you may not use this file except in compliance with the License. | ||
8 | + * You may obtain a copy of the License at | ||
9 | + * | ||
10 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
11 | + * | ||
12 | + * Unless required by applicable law or agreed to in writing, software | ||
13 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
14 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
15 | + * See the License for the specific language governing permissions and | ||
16 | + * limitations under the License. | ||
17 | + */ | ||
18 | + | ||
19 | +import org.apache.karaf.shell.commands.Command; | ||
20 | +import org.onosproject.cli.AbstractShellCommand; | ||
21 | +import org.onosproject.net.DeviceId; | ||
22 | +import org.onosproject.net.device.DeviceService; | ||
23 | +import org.onosproject.net.device.PortStatistics; | ||
24 | + | ||
25 | +/** | ||
26 | + * Lists port statistic of all ports in the system. | ||
27 | + */ | ||
28 | +@Command(scope = "onos", name = "portstats", | ||
29 | + description = "Lists statistics of all ports in the system") | ||
30 | +public class DevicePortStatsCommand extends AbstractShellCommand { | ||
31 | + | ||
32 | + private static final String FORMAT = | ||
33 | + " port=%s, pktRx=%s, pktTx=%s, bytesRx=%s, bytesTx=%s, pktRxDrp=%s, pktTxDrp=%s, Dur=%s"; | ||
34 | + | ||
35 | + @Override | ||
36 | + protected void execute() { | ||
37 | + DeviceService deviceService = get(DeviceService.class); | ||
38 | + | ||
39 | + deviceService.getDevices().forEach(d -> | ||
40 | + printPortStats(d.id(), deviceService.getPortStatistics(d.id())) | ||
41 | + ); | ||
42 | + } | ||
43 | + | ||
44 | + private void printPortStats(DeviceId deviceId, Iterable<PortStatistics> portStats) { | ||
45 | + print("deviceId=%s", deviceId); | ||
46 | + for (PortStatistics stat : portStats) { | ||
47 | + print(FORMAT, stat.port(), stat.packetsReceived(), stat.packetsSent(), stat.bytesReceived(), | ||
48 | + stat.bytesSent(), stat.packetsRxDropped(), stat.packetsTxDropped(), stat.durationSec()); | ||
49 | + } | ||
50 | + } | ||
51 | +} |
... | @@ -280,6 +280,10 @@ | ... | @@ -280,6 +280,10 @@ |
280 | </command> | 280 | </command> |
281 | 281 | ||
282 | <command> | 282 | <command> |
283 | + <action class="org.onosproject.cli.net.DevicePortStatsCommand"/> | ||
284 | + </command> | ||
285 | + | ||
286 | + <command> | ||
283 | <action class="org.onosproject.cli.net.FlowsListCommand"/> | 287 | <action class="org.onosproject.cli.net.FlowsListCommand"/> |
284 | <completers> | 288 | <completers> |
285 | <ref component-id="flowRuleStatusCompleter"/> | 289 | <ref component-id="flowRuleStatusCompleter"/> | ... | ... |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
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 | +package org.onosproject.net.device; | ||
17 | + | ||
18 | +import org.onosproject.net.DeviceId; | ||
19 | + | ||
20 | +/** | ||
21 | + * Default implementation of immutable port statistics. | ||
22 | + */ | ||
23 | +public final class DefaultPortStatistics implements PortStatistics { | ||
24 | + | ||
25 | + private final DeviceId deviceId; | ||
26 | + private final int port; | ||
27 | + private final long packetsReceived; | ||
28 | + private final long packetsSent; | ||
29 | + private final long bytesReceived; | ||
30 | + private final long bytesSent; | ||
31 | + private final long packetsRxDropped; | ||
32 | + private final long packetsTxDropped; | ||
33 | + private final long packetsRxErrors; | ||
34 | + private final long packetsTxErrors; | ||
35 | + private final long durationSec; | ||
36 | + private final long durationNano; | ||
37 | + | ||
38 | + private DefaultPortStatistics(DeviceId deviceId, | ||
39 | + int port, | ||
40 | + long packetsReceived, | ||
41 | + long packetsSent, | ||
42 | + long bytesReceived, | ||
43 | + long bytesSent, | ||
44 | + long packetsRxDropped, | ||
45 | + long packetsTxDropped, | ||
46 | + long packetsRxErrors, | ||
47 | + long packetsTxErrors, | ||
48 | + long durationSec, | ||
49 | + long durationNano) { | ||
50 | + this.deviceId = deviceId; | ||
51 | + this.port = port; | ||
52 | + this.packetsReceived = packetsReceived; | ||
53 | + this.packetsSent = packetsSent; | ||
54 | + this.bytesReceived = bytesReceived; | ||
55 | + this.bytesSent = bytesSent; | ||
56 | + this.packetsRxDropped = packetsRxDropped; | ||
57 | + this.packetsTxDropped = packetsTxDropped; | ||
58 | + this.packetsRxErrors = packetsRxErrors; | ||
59 | + this.packetsTxErrors = packetsTxErrors; | ||
60 | + this.durationSec = durationSec; | ||
61 | + this.durationNano = durationNano; | ||
62 | + } | ||
63 | + | ||
64 | + /** | ||
65 | + * Creates a builder for DefaultPortStatistics object. | ||
66 | + * | ||
67 | + * @return builder object for DefaultPortStatistics object | ||
68 | + */ | ||
69 | + public static DefaultPortStatistics.Builder builder() { | ||
70 | + return new Builder(); | ||
71 | + } | ||
72 | + | ||
73 | + @Override | ||
74 | + public int port() { | ||
75 | + return this.port; | ||
76 | + } | ||
77 | + | ||
78 | + @Override | ||
79 | + public long packetsReceived() { | ||
80 | + return this.packetsReceived; | ||
81 | + } | ||
82 | + | ||
83 | + @Override | ||
84 | + public long packetsSent() { | ||
85 | + return this.packetsSent; | ||
86 | + } | ||
87 | + | ||
88 | + @Override | ||
89 | + public long bytesReceived() { | ||
90 | + return this.bytesReceived; | ||
91 | + } | ||
92 | + | ||
93 | + @Override | ||
94 | + public long bytesSent() { | ||
95 | + return this.bytesSent; | ||
96 | + } | ||
97 | + | ||
98 | + @Override | ||
99 | + public long packetsRxDropped() { | ||
100 | + return this.packetsRxDropped; | ||
101 | + } | ||
102 | + | ||
103 | + @Override | ||
104 | + public long packetsTxDropped() { | ||
105 | + return this.packetsTxDropped; | ||
106 | + } | ||
107 | + | ||
108 | + @Override | ||
109 | + public long packetsRxErrors() { | ||
110 | + return this.packetsRxErrors; | ||
111 | + } | ||
112 | + | ||
113 | + @Override | ||
114 | + public long packetsTxErrors() { | ||
115 | + return this.packetsTxErrors; | ||
116 | + } | ||
117 | + | ||
118 | + @Override | ||
119 | + public long durationSec() { | ||
120 | + return this.durationSec; | ||
121 | + } | ||
122 | + | ||
123 | + @Override | ||
124 | + public long durationNano() { | ||
125 | + return this.durationNano; | ||
126 | + } | ||
127 | + | ||
128 | + @Override | ||
129 | + public String toString() { | ||
130 | + StringBuilder sb = new StringBuilder("device: " + deviceId + ", "); | ||
131 | + | ||
132 | + sb.append("port: " + this.port + ", "); | ||
133 | + sb.append("pktRx: " + this.packetsReceived + ", "); | ||
134 | + sb.append("pktTx: " + this.packetsSent + ", "); | ||
135 | + sb.append("byteRx: " + this.bytesReceived + ", "); | ||
136 | + sb.append("byteTx: " + this.bytesSent + ", "); | ||
137 | + sb.append("pktRxErr: " + this.packetsRxErrors + ", "); | ||
138 | + sb.append("pktTxErr: " + this.packetsTxErrors + ", "); | ||
139 | + sb.append("pktRxDrp: " + this.packetsRxDropped + ", "); | ||
140 | + sb.append("pktTxDrp: " + this.packetsTxDropped); | ||
141 | + | ||
142 | + return sb.toString(); | ||
143 | + } | ||
144 | + | ||
145 | + public static final class Builder { | ||
146 | + | ||
147 | + DeviceId deviceId; | ||
148 | + int port; | ||
149 | + long packetsReceived; | ||
150 | + long packetsSent; | ||
151 | + long bytesReceived; | ||
152 | + long bytesSent; | ||
153 | + long packetsRxDropped; | ||
154 | + long packetsTxDropped; | ||
155 | + long packetsRxErrors; | ||
156 | + long packetsTxErrors; | ||
157 | + long durationSec; | ||
158 | + long durationNano; | ||
159 | + | ||
160 | + private Builder() { | ||
161 | + | ||
162 | + } | ||
163 | + | ||
164 | + /** | ||
165 | + * Sets port number. | ||
166 | + * | ||
167 | + * @param port port number | ||
168 | + * @return builder object | ||
169 | + */ | ||
170 | + public Builder setPort(int port) { | ||
171 | + this.port = port; | ||
172 | + | ||
173 | + return this; | ||
174 | + } | ||
175 | + | ||
176 | + /** | ||
177 | + * Sets the device identifier. | ||
178 | + * | ||
179 | + * @param deviceId device identifier | ||
180 | + * @return builder object | ||
181 | + */ | ||
182 | + public Builder setDeviceId(DeviceId deviceId) { | ||
183 | + this.deviceId = deviceId; | ||
184 | + | ||
185 | + return this; | ||
186 | + } | ||
187 | + | ||
188 | + /** | ||
189 | + * Sets the number of packet received. | ||
190 | + * | ||
191 | + * @param packets number of packets received | ||
192 | + * @return builder object | ||
193 | + */ | ||
194 | + public Builder setPacketsReceived(long packets) { | ||
195 | + packetsReceived = packets; | ||
196 | + | ||
197 | + return this; | ||
198 | + } | ||
199 | + | ||
200 | + /** | ||
201 | + * Sets the number of packets sent. | ||
202 | + * | ||
203 | + * @param packets number of packets sent | ||
204 | + * @return builder object | ||
205 | + */ | ||
206 | + public Builder setPacketsSent(long packets) { | ||
207 | + packetsSent = packets; | ||
208 | + | ||
209 | + return this; | ||
210 | + } | ||
211 | + | ||
212 | + /** | ||
213 | + * Sets the number of received bytes. | ||
214 | + * | ||
215 | + * @param bytes number of received bytes. | ||
216 | + * @return builder object | ||
217 | + */ | ||
218 | + public Builder setBytesReceived(long bytes) { | ||
219 | + bytesReceived = bytes; | ||
220 | + | ||
221 | + return this; | ||
222 | + } | ||
223 | + | ||
224 | + /** | ||
225 | + * Sets the number of sent bytes. | ||
226 | + * | ||
227 | + * @param bytes number of sent bytes | ||
228 | + * @return builder object | ||
229 | + */ | ||
230 | + public Builder setBytesSent(long bytes) { | ||
231 | + bytesSent = bytes; | ||
232 | + | ||
233 | + return this; | ||
234 | + } | ||
235 | + | ||
236 | + /** | ||
237 | + * Sets the number of packets dropped by RX. | ||
238 | + * | ||
239 | + * @param packets number of packets dropped by RX | ||
240 | + * @return builder object | ||
241 | + */ | ||
242 | + public Builder setPacketsRxDropped(long packets) { | ||
243 | + packetsRxDropped = packets; | ||
244 | + | ||
245 | + return this; | ||
246 | + } | ||
247 | + | ||
248 | + /** | ||
249 | + * Sets the number of packets dropped by TX. | ||
250 | + * | ||
251 | + * @param packets | ||
252 | + * @return builder object | ||
253 | + */ | ||
254 | + public Builder setPacketsTxDropped(long packets) { | ||
255 | + packetsTxDropped = packets; | ||
256 | + | ||
257 | + return this; | ||
258 | + } | ||
259 | + | ||
260 | + /** | ||
261 | + * Sets the number of receive errors. | ||
262 | + * | ||
263 | + * @param packets number of receive errors | ||
264 | + * @return builder object | ||
265 | + */ | ||
266 | + public Builder setPacketsRxErrors(long packets) { | ||
267 | + packetsRxErrors = packets; | ||
268 | + | ||
269 | + return this; | ||
270 | + } | ||
271 | + | ||
272 | + /** | ||
273 | + * Sets the number of transmit errors. | ||
274 | + * | ||
275 | + * @param packets number of transmit errors | ||
276 | + * @return builder object | ||
277 | + */ | ||
278 | + public Builder setPacketsTxErrors(long packets) { | ||
279 | + packetsTxErrors = packets; | ||
280 | + | ||
281 | + return this; | ||
282 | + } | ||
283 | + | ||
284 | + /** | ||
285 | + * Sets the time port has been alive in seconds. | ||
286 | + * | ||
287 | + * @param sec time port has been alive in seconds | ||
288 | + * @return builder object | ||
289 | + */ | ||
290 | + public Builder setDurationSec(long sec) { | ||
291 | + durationSec = sec; | ||
292 | + | ||
293 | + return this; | ||
294 | + } | ||
295 | + | ||
296 | + /** | ||
297 | + * Sets the time port has been alive in nano seconds. | ||
298 | + * | ||
299 | + * @param nano time port has been alive in nano seconds | ||
300 | + * @return builder object | ||
301 | + */ | ||
302 | + public Builder setDurationNano(long nano) { | ||
303 | + durationNano = nano; | ||
304 | + | ||
305 | + return this; | ||
306 | + } | ||
307 | + | ||
308 | + /** | ||
309 | + * Creates a PortStatistics object. | ||
310 | + * | ||
311 | + * @return DefaultPortStatistics object | ||
312 | + */ | ||
313 | + public DefaultPortStatistics build() { | ||
314 | + return new DefaultPortStatistics( | ||
315 | + deviceId, | ||
316 | + port, | ||
317 | + packetsReceived, | ||
318 | + packetsSent, | ||
319 | + bytesReceived, | ||
320 | + bytesSent, | ||
321 | + packetsRxDropped, | ||
322 | + packetsTxDropped, | ||
323 | + packetsRxErrors, | ||
324 | + packetsTxErrors, | ||
325 | + durationSec, | ||
326 | + durationNano); | ||
327 | + } | ||
328 | + | ||
329 | + } | ||
330 | +} |
... | @@ -72,7 +72,12 @@ public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> { | ... | @@ -72,7 +72,12 @@ public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> { |
72 | /** | 72 | /** |
73 | * Signifies that a port has been removed. | 73 | * Signifies that a port has been removed. |
74 | */ | 74 | */ |
75 | - PORT_REMOVED | 75 | + PORT_REMOVED, |
76 | + | ||
77 | + /* | ||
78 | + * Signifies that port statistics has been updated. | ||
79 | + */ | ||
80 | + PORT_STATS_UPDATED | ||
76 | } | 81 | } |
77 | 82 | ||
78 | /** | 83 | /** | ... | ... |
... | @@ -19,6 +19,7 @@ import org.onosproject.net.DeviceId; | ... | @@ -19,6 +19,7 @@ import org.onosproject.net.DeviceId; |
19 | import org.onosproject.net.MastershipRole; | 19 | import org.onosproject.net.MastershipRole; |
20 | import org.onosproject.net.provider.ProviderService; | 20 | import org.onosproject.net.provider.ProviderService; |
21 | 21 | ||
22 | +import java.util.Collection; | ||
22 | import java.util.List; | 23 | import java.util.List; |
23 | 24 | ||
24 | /** | 25 | /** |
... | @@ -70,4 +71,12 @@ public interface DeviceProviderService extends ProviderService<DeviceProvider> { | ... | @@ -70,4 +71,12 @@ public interface DeviceProviderService extends ProviderService<DeviceProvider> { |
70 | */ | 71 | */ |
71 | void receivedRoleReply(DeviceId deviceId, MastershipRole requested, MastershipRole response); | 72 | void receivedRoleReply(DeviceId deviceId, MastershipRole requested, MastershipRole response); |
72 | 73 | ||
74 | + /** | ||
75 | + * Sends statistics about all ports of a device. | ||
76 | + * | ||
77 | + * @param deviceId identity of the device | ||
78 | + * @param portStatistics list of device port statistics | ||
79 | + */ | ||
80 | + void updatePortStatistics(DeviceId deviceId, Collection<PortStatistics> portStatistics); | ||
81 | + | ||
73 | } | 82 | } | ... | ... |
... | @@ -78,6 +78,14 @@ public interface DeviceService { | ... | @@ -78,6 +78,14 @@ public interface DeviceService { |
78 | List<Port> getPorts(DeviceId deviceId); | 78 | List<Port> getPorts(DeviceId deviceId); |
79 | 79 | ||
80 | /** | 80 | /** |
81 | + * Returns the list of port statistics associated with the device. | ||
82 | + * | ||
83 | + * @param deviceId device identitifer | ||
84 | + * @return list of port statistics | ||
85 | + */ | ||
86 | + List<PortStatistics> getPortStatistics(DeviceId deviceId); | ||
87 | + | ||
88 | + /** | ||
81 | * Returns the port with the specified number and hosted by the given device. | 89 | * Returns the port with the specified number and hosted by the given device. |
82 | * | 90 | * |
83 | * @param deviceId device identifier | 91 | * @param deviceId device identifier | ... | ... |
... | @@ -22,6 +22,7 @@ import org.onosproject.net.PortNumber; | ... | @@ -22,6 +22,7 @@ import org.onosproject.net.PortNumber; |
22 | import org.onosproject.net.provider.ProviderId; | 22 | import org.onosproject.net.provider.ProviderId; |
23 | import org.onosproject.store.Store; | 23 | import org.onosproject.store.Store; |
24 | 24 | ||
25 | +import java.util.Collection; | ||
25 | import java.util.List; | 26 | import java.util.List; |
26 | 27 | ||
27 | /** | 28 | /** |
... | @@ -114,6 +115,26 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> { | ... | @@ -114,6 +115,26 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> { |
114 | List<Port> getPorts(DeviceId deviceId); | 115 | List<Port> getPorts(DeviceId deviceId); |
115 | 116 | ||
116 | /** | 117 | /** |
118 | + * Updates the port statistics of the specified device using the give port | ||
119 | + * statistics. | ||
120 | + * | ||
121 | + * @param providerId provider identifier | ||
122 | + * @param deviceId device identifier | ||
123 | + * @param portStats list of port statistics | ||
124 | + * @return ready to send event describing what occurred; | ||
125 | + */ | ||
126 | + DeviceEvent updatePortStatistics(ProviderId providerId, DeviceId deviceId, | ||
127 | + Collection<PortStatistics> portStats); | ||
128 | + | ||
129 | + /** | ||
130 | + * Returns the list of port statistics of the specified device. | ||
131 | + * | ||
132 | + * @param deviceId device identifier | ||
133 | + * @return list of port statistics of all ports of the device | ||
134 | + */ | ||
135 | + List<PortStatistics> getPortStatistics(DeviceId deviceId); | ||
136 | + | ||
137 | + /** | ||
117 | * Returns the specified device port. | 138 | * Returns the specified device port. |
118 | * | 139 | * |
119 | * @param deviceId device identifier | 140 | * @param deviceId device identifier |
... | @@ -137,4 +158,6 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> { | ... | @@ -137,4 +158,6 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> { |
137 | * @return null if no such device, or was forwarded to remove master | 158 | * @return null if no such device, or was forwarded to remove master |
138 | */ | 159 | */ |
139 | DeviceEvent removeDevice(DeviceId deviceId); | 160 | DeviceEvent removeDevice(DeviceId deviceId); |
161 | + | ||
162 | + | ||
140 | } | 163 | } | ... | ... |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
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 | +package org.onosproject.net.device; | ||
17 | + | ||
18 | +/** | ||
19 | + * Statistics of a port. | ||
20 | + */ | ||
21 | +public interface PortStatistics { | ||
22 | + | ||
23 | + /** | ||
24 | + * Returns the port number. | ||
25 | + * | ||
26 | + * @return port number | ||
27 | + */ | ||
28 | + public int port(); | ||
29 | + | ||
30 | + /** | ||
31 | + * Returns the number of packets received. | ||
32 | + * | ||
33 | + * @return the number of packets received | ||
34 | + */ | ||
35 | + public long packetsReceived(); | ||
36 | + | ||
37 | + /** | ||
38 | + * Returns the number of packets sent. | ||
39 | + * | ||
40 | + * @return the number of packets sent | ||
41 | + */ | ||
42 | + public long packetsSent(); | ||
43 | + | ||
44 | + /** | ||
45 | + * Returns the bytes received. | ||
46 | + * | ||
47 | + * @return the bytes received | ||
48 | + */ | ||
49 | + public long bytesReceived(); | ||
50 | + | ||
51 | + /** | ||
52 | + * Returns the bytes sent. | ||
53 | + * | ||
54 | + * @return the bytes sent | ||
55 | + */ | ||
56 | + public long bytesSent(); | ||
57 | + | ||
58 | + /** | ||
59 | + * Returns the number of packets dropped by RX. | ||
60 | + * | ||
61 | + * @return the number of packets dropped by RX | ||
62 | + */ | ||
63 | + public long packetsRxDropped(); | ||
64 | + | ||
65 | + /** | ||
66 | + * Returns the number of packets dropped by TX. | ||
67 | + * | ||
68 | + * @return the number of packets dropped by TX | ||
69 | + */ | ||
70 | + public long packetsTxDropped(); | ||
71 | + | ||
72 | + /** | ||
73 | + * Returns the number of transmit errors. | ||
74 | + * | ||
75 | + * @return the number of transmit errors | ||
76 | + */ | ||
77 | + public long packetsRxErrors(); | ||
78 | + | ||
79 | + /** | ||
80 | + * Returns the number of receive errors. | ||
81 | + * | ||
82 | + * @return the number of receive error | ||
83 | + */ | ||
84 | + public long packetsTxErrors(); | ||
85 | + | ||
86 | + /** | ||
87 | + * Returns the time port has been alive in seconds. | ||
88 | + * | ||
89 | + * @return the time port has been alive in seconds | ||
90 | + */ | ||
91 | + public long durationSec(); | ||
92 | + | ||
93 | + /** | ||
94 | + * Returns the time port has been alive in nano seconds. | ||
95 | + * | ||
96 | + * @return the time port has been alive in nano seconds | ||
97 | + */ | ||
98 | + public long durationNano(); | ||
99 | + | ||
100 | +} |
... | @@ -69,6 +69,11 @@ public class DeviceServiceAdapter implements DeviceService { | ... | @@ -69,6 +69,11 @@ public class DeviceServiceAdapter implements DeviceService { |
69 | } | 69 | } |
70 | 70 | ||
71 | @Override | 71 | @Override |
72 | + public List<PortStatistics> getPortStatistics(DeviceId deviceId) { | ||
73 | + return null; | ||
74 | + } | ||
75 | + | ||
76 | + @Override | ||
72 | public Port getPort(DeviceId deviceId, PortNumber portNumber) { | 77 | public Port getPort(DeviceId deviceId, PortNumber portNumber) { |
73 | return null; | 78 | return null; |
74 | } | 79 | } | ... | ... |
... | @@ -50,10 +50,12 @@ import org.onosproject.net.device.DeviceService; | ... | @@ -50,10 +50,12 @@ import org.onosproject.net.device.DeviceService; |
50 | import org.onosproject.net.device.DeviceStore; | 50 | import org.onosproject.net.device.DeviceStore; |
51 | import org.onosproject.net.device.DeviceStoreDelegate; | 51 | import org.onosproject.net.device.DeviceStoreDelegate; |
52 | import org.onosproject.net.device.PortDescription; | 52 | import org.onosproject.net.device.PortDescription; |
53 | +import org.onosproject.net.device.PortStatistics; | ||
53 | import org.onosproject.net.provider.AbstractProviderRegistry; | 54 | import org.onosproject.net.provider.AbstractProviderRegistry; |
54 | import org.onosproject.net.provider.AbstractProviderService; | 55 | import org.onosproject.net.provider.AbstractProviderService; |
55 | import org.slf4j.Logger; | 56 | import org.slf4j.Logger; |
56 | 57 | ||
58 | +import java.util.Collection; | ||
57 | import java.util.List; | 59 | import java.util.List; |
58 | import java.util.concurrent.ScheduledExecutorService; | 60 | import java.util.concurrent.ScheduledExecutorService; |
59 | import java.util.concurrent.TimeUnit; | 61 | import java.util.concurrent.TimeUnit; |
... | @@ -174,6 +176,12 @@ public class DeviceManager | ... | @@ -174,6 +176,12 @@ public class DeviceManager |
174 | } | 176 | } |
175 | 177 | ||
176 | @Override | 178 | @Override |
179 | + public List<PortStatistics> getPortStatistics(DeviceId deviceId) { | ||
180 | + checkNotNull(deviceId, DEVICE_ID_NULL); | ||
181 | + return store.getPortStatistics(deviceId); | ||
182 | + } | ||
183 | + | ||
184 | + @Override | ||
177 | public Port getPort(DeviceId deviceId, PortNumber portNumber) { | 185 | public Port getPort(DeviceId deviceId, PortNumber portNumber) { |
178 | checkNotNull(deviceId, DEVICE_ID_NULL); | 186 | checkNotNull(deviceId, DEVICE_ID_NULL); |
179 | checkNotNull(portNumber, PORT_NUMBER_NULL); | 187 | checkNotNull(portNumber, PORT_NUMBER_NULL); |
... | @@ -463,6 +471,19 @@ public class DeviceManager | ... | @@ -463,6 +471,19 @@ public class DeviceManager |
463 | } | 471 | } |
464 | 472 | ||
465 | } | 473 | } |
474 | + | ||
475 | + @Override | ||
476 | + public void updatePortStatistics(DeviceId deviceId, Collection<PortStatistics> portStatistics) { | ||
477 | + checkNotNull(deviceId, DEVICE_ID_NULL); | ||
478 | + checkNotNull(portStatistics, | ||
479 | + "Port statistics list cannot be null"); | ||
480 | + checkValidity(); | ||
481 | + | ||
482 | + DeviceEvent event = store.updatePortStatistics(this.provider().id(), | ||
483 | + deviceId, portStatistics); | ||
484 | + | ||
485 | + post(event); | ||
486 | + } | ||
466 | } | 487 | } |
467 | 488 | ||
468 | // Posts the specified event to the local event dispatcher. | 489 | // Posts the specified event to the local event dispatcher. | ... | ... |
... | @@ -53,6 +53,7 @@ import org.onosproject.net.device.DeviceEvent; | ... | @@ -53,6 +53,7 @@ import org.onosproject.net.device.DeviceEvent; |
53 | import org.onosproject.net.device.DeviceStore; | 53 | import org.onosproject.net.device.DeviceStore; |
54 | import org.onosproject.net.device.DeviceStoreDelegate; | 54 | import org.onosproject.net.device.DeviceStoreDelegate; |
55 | import org.onosproject.net.device.PortDescription; | 55 | import org.onosproject.net.device.PortDescription; |
56 | +import org.onosproject.net.device.PortStatistics; | ||
56 | import org.onosproject.net.provider.ProviderId; | 57 | import org.onosproject.net.provider.ProviderId; |
57 | import org.onosproject.store.AbstractStore; | 58 | import org.onosproject.store.AbstractStore; |
58 | import org.onosproject.store.Timestamp; | 59 | import org.onosproject.store.Timestamp; |
... | @@ -121,6 +122,8 @@ public class GossipDeviceStore | ... | @@ -121,6 +122,8 @@ public class GossipDeviceStore |
121 | // cache of Device and Ports generated by compositing descriptions from providers | 122 | // cache of Device and Ports generated by compositing descriptions from providers |
122 | private final ConcurrentMap<DeviceId, Device> devices = Maps.newConcurrentMap(); | 123 | private final ConcurrentMap<DeviceId, Device> devices = Maps.newConcurrentMap(); |
123 | private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, Port>> devicePorts = Maps.newConcurrentMap(); | 124 | private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, Port>> devicePorts = Maps.newConcurrentMap(); |
125 | + private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, PortStatistics>> | ||
126 | + devicePortStats = Maps.newConcurrentMap(); | ||
124 | 127 | ||
125 | // to be updated under Device lock | 128 | // to be updated under Device lock |
126 | private final Map<DeviceId, Timestamp> offline = Maps.newHashMap(); | 129 | private final Map<DeviceId, Timestamp> offline = Maps.newHashMap(); |
... | @@ -800,6 +803,34 @@ public class GossipDeviceStore | ... | @@ -800,6 +803,34 @@ public class GossipDeviceStore |
800 | } | 803 | } |
801 | 804 | ||
802 | @Override | 805 | @Override |
806 | + public DeviceEvent updatePortStatistics(ProviderId providerId, DeviceId deviceId, | ||
807 | + Collection<PortStatistics> portStats) { | ||
808 | + | ||
809 | + ConcurrentMap<PortNumber, PortStatistics> statsMap = devicePortStats.get(deviceId); | ||
810 | + if (statsMap == null) { | ||
811 | + statsMap = Maps.newConcurrentMap(); | ||
812 | + devicePortStats.put(deviceId, statsMap); | ||
813 | + } | ||
814 | + | ||
815 | + for (PortStatistics stat: portStats) { | ||
816 | + PortNumber portNumber = PortNumber.portNumber(stat.port()); | ||
817 | + statsMap.put(portNumber, stat); | ||
818 | + } | ||
819 | + | ||
820 | + return new DeviceEvent(PORT_STATS_UPDATED, devices.get(deviceId), null); | ||
821 | + } | ||
822 | + | ||
823 | + @Override | ||
824 | + public List<PortStatistics> getPortStatistics(DeviceId deviceId) { | ||
825 | + | ||
826 | + Map<PortNumber, PortStatistics> portStats = devicePortStats.get(deviceId); | ||
827 | + if (portStats == null) { | ||
828 | + return Collections.emptyList(); | ||
829 | + } | ||
830 | + return ImmutableList.copyOf(portStats.values()); | ||
831 | + } | ||
832 | + | ||
833 | + @Override | ||
803 | public Port getPort(DeviceId deviceId, PortNumber portNumber) { | 834 | public Port getPort(DeviceId deviceId, PortNumber portNumber) { |
804 | Map<PortNumber, Port> ports = devicePorts.get(deviceId); | 835 | Map<PortNumber, Port> ports = devicePorts.get(deviceId); |
805 | return ports == null ? null : ports.get(portNumber); | 836 | return ports == null ? null : ports.get(portNumber); | ... | ... |
... | @@ -42,6 +42,7 @@ import org.onosproject.net.device.DeviceEvent; | ... | @@ -42,6 +42,7 @@ import org.onosproject.net.device.DeviceEvent; |
42 | import org.onosproject.net.device.DeviceStore; | 42 | import org.onosproject.net.device.DeviceStore; |
43 | import org.onosproject.net.device.DeviceStoreDelegate; | 43 | import org.onosproject.net.device.DeviceStoreDelegate; |
44 | import org.onosproject.net.device.PortDescription; | 44 | import org.onosproject.net.device.PortDescription; |
45 | +import org.onosproject.net.device.PortStatistics; | ||
45 | import org.onosproject.net.provider.ProviderId; | 46 | import org.onosproject.net.provider.ProviderId; |
46 | import org.onosproject.store.AbstractStore; | 47 | import org.onosproject.store.AbstractStore; |
47 | import org.onlab.packet.ChassisId; | 48 | import org.onlab.packet.ChassisId; |
... | @@ -49,6 +50,7 @@ import org.onlab.util.NewConcurrentHashMap; | ... | @@ -49,6 +50,7 @@ import org.onlab.util.NewConcurrentHashMap; |
49 | import org.slf4j.Logger; | 50 | import org.slf4j.Logger; |
50 | 51 | ||
51 | import java.util.ArrayList; | 52 | import java.util.ArrayList; |
53 | +import java.util.Collection; | ||
52 | import java.util.Collections; | 54 | import java.util.Collections; |
53 | import java.util.HashMap; | 55 | import java.util.HashMap; |
54 | import java.util.HashSet; | 56 | import java.util.HashSet; |
... | @@ -94,6 +96,8 @@ public class SimpleDeviceStore | ... | @@ -94,6 +96,8 @@ public class SimpleDeviceStore |
94 | private final ConcurrentMap<DeviceId, Device> devices = Maps.newConcurrentMap(); | 96 | private final ConcurrentMap<DeviceId, Device> devices = Maps.newConcurrentMap(); |
95 | private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, Port>> | 97 | private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, Port>> |
96 | devicePorts = Maps.newConcurrentMap(); | 98 | devicePorts = Maps.newConcurrentMap(); |
99 | + private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, PortStatistics>> | ||
100 | + devicePortStats = Maps.newConcurrentMap(); | ||
97 | 101 | ||
98 | // Available (=UP) devices | 102 | // Available (=UP) devices |
99 | private final Set<DeviceId> availableDevices = Sets.newConcurrentHashSet(); | 103 | private final Set<DeviceId> availableDevices = Sets.newConcurrentHashSet(); |
... | @@ -416,12 +420,39 @@ public class SimpleDeviceStore | ... | @@ -416,12 +420,39 @@ public class SimpleDeviceStore |
416 | } | 420 | } |
417 | 421 | ||
418 | @Override | 422 | @Override |
423 | + public DeviceEvent updatePortStatistics(ProviderId providerId, DeviceId deviceId, | ||
424 | + Collection<PortStatistics> portStats) { | ||
425 | + | ||
426 | + ConcurrentMap<PortNumber, PortStatistics> statsMap = devicePortStats.get(deviceId); | ||
427 | + if (statsMap == null) { | ||
428 | + statsMap = Maps.newConcurrentMap(); | ||
429 | + devicePortStats.put(deviceId, statsMap); | ||
430 | + } | ||
431 | + | ||
432 | + for (PortStatistics stat: portStats) { | ||
433 | + PortNumber portNumber = PortNumber.portNumber(stat.port()); | ||
434 | + statsMap.put(portNumber, stat); | ||
435 | + } | ||
436 | + | ||
437 | + return new DeviceEvent(PORT_STATS_UPDATED, devices.get(deviceId), null); | ||
438 | + } | ||
439 | + | ||
440 | + @Override | ||
419 | public Port getPort(DeviceId deviceId, PortNumber portNumber) { | 441 | public Port getPort(DeviceId deviceId, PortNumber portNumber) { |
420 | Map<PortNumber, Port> ports = devicePorts.get(deviceId); | 442 | Map<PortNumber, Port> ports = devicePorts.get(deviceId); |
421 | return ports == null ? null : ports.get(portNumber); | 443 | return ports == null ? null : ports.get(portNumber); |
422 | } | 444 | } |
423 | 445 | ||
424 | @Override | 446 | @Override |
447 | + public List<PortStatistics> getPortStatistics(DeviceId deviceId) { | ||
448 | + Map<PortNumber, PortStatistics> portStats = devicePortStats.get(deviceId); | ||
449 | + if (portStats == null) { | ||
450 | + return Collections.emptyList(); | ||
451 | + } | ||
452 | + return ImmutableList.copyOf(portStats.values()); | ||
453 | + } | ||
454 | + | ||
455 | + @Override | ||
425 | public boolean isAvailable(DeviceId deviceId) { | 456 | public boolean isAvailable(DeviceId deviceId) { |
426 | return availableDevices.contains(deviceId); | 457 | return availableDevices.contains(deviceId); |
427 | } | 458 | } | ... | ... |
... | @@ -47,6 +47,8 @@ import org.projectfloodlight.openflow.protocol.OFGroupStatsReply; | ... | @@ -47,6 +47,8 @@ import org.projectfloodlight.openflow.protocol.OFGroupStatsReply; |
47 | import org.projectfloodlight.openflow.protocol.OFMessage; | 47 | import org.projectfloodlight.openflow.protocol.OFMessage; |
48 | import org.projectfloodlight.openflow.protocol.OFPacketIn; | 48 | import org.projectfloodlight.openflow.protocol.OFPacketIn; |
49 | import org.projectfloodlight.openflow.protocol.OFPortDesc; | 49 | import org.projectfloodlight.openflow.protocol.OFPortDesc; |
50 | +import org.projectfloodlight.openflow.protocol.OFPortStatsEntry; | ||
51 | +import org.projectfloodlight.openflow.protocol.OFPortStatsReply; | ||
50 | import org.projectfloodlight.openflow.protocol.OFPortStatus; | 52 | import org.projectfloodlight.openflow.protocol.OFPortStatus; |
51 | import org.projectfloodlight.openflow.protocol.OFStatsReply; | 53 | import org.projectfloodlight.openflow.protocol.OFStatsReply; |
52 | import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags; | 54 | import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags; |
... | @@ -104,6 +106,9 @@ public class OpenFlowControllerImpl implements OpenFlowController { | ... | @@ -104,6 +106,9 @@ public class OpenFlowControllerImpl implements OpenFlowController { |
104 | protected Multimap<Dpid, OFGroupDescStatsEntry> fullGroupDescStats = | 106 | protected Multimap<Dpid, OFGroupDescStatsEntry> fullGroupDescStats = |
105 | ArrayListMultimap.create(); | 107 | ArrayListMultimap.create(); |
106 | 108 | ||
109 | + protected Multimap<Dpid, OFPortStatsEntry> fullPortStats = | ||
110 | + ArrayListMultimap.create(); | ||
111 | + | ||
107 | private final Controller ctrl = new Controller(); | 112 | private final Controller ctrl = new Controller(); |
108 | 113 | ||
109 | @Activate | 114 | @Activate |
... | @@ -216,6 +221,7 @@ public class OpenFlowControllerImpl implements OpenFlowController { | ... | @@ -216,6 +221,7 @@ public class OpenFlowControllerImpl implements OpenFlowController { |
216 | Collection<OFFlowStatsEntry> flowStats; | 221 | Collection<OFFlowStatsEntry> flowStats; |
217 | Collection<OFGroupStatsEntry> groupStats; | 222 | Collection<OFGroupStatsEntry> groupStats; |
218 | Collection<OFGroupDescStatsEntry> groupDescStats; | 223 | Collection<OFGroupDescStatsEntry> groupDescStats; |
224 | + Collection<OFPortStatsEntry> portStats; | ||
219 | 225 | ||
220 | switch (msg.getType()) { | 226 | switch (msg.getType()) { |
221 | case PORT_STATUS: | 227 | case PORT_STATUS: |
... | @@ -280,6 +286,9 @@ public class OpenFlowControllerImpl implements OpenFlowController { | ... | @@ -280,6 +286,9 @@ public class OpenFlowControllerImpl implements OpenFlowController { |
280 | executorMsgs.submit(new OFMessageHandler(dpid, rep.build())); | 286 | executorMsgs.submit(new OFMessageHandler(dpid, rep.build())); |
281 | } | 287 | } |
282 | break; | 288 | break; |
289 | + case PORT: | ||
290 | + executorMsgs.submit(new OFMessageHandler(dpid, reply)); | ||
291 | + break; | ||
283 | default: | 292 | default: |
284 | log.warn("Unsupported stats type : {}", reply.getStatsType()); | 293 | log.warn("Unsupported stats type : {}", reply.getStatsType()); |
285 | } | 294 | } |
... | @@ -343,6 +352,15 @@ public class OpenFlowControllerImpl implements OpenFlowController { | ... | @@ -343,6 +352,15 @@ public class OpenFlowControllerImpl implements OpenFlowController { |
343 | return null; | 352 | return null; |
344 | } | 353 | } |
345 | 354 | ||
355 | + private synchronized Collection<OFPortStatsEntry> publishPortStats(Dpid dpid, | ||
356 | + OFPortStatsReply reply) { | ||
357 | + fullPortStats.putAll(dpid, reply.getEntries()); | ||
358 | + if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) { | ||
359 | + return fullPortStats.removeAll(dpid); | ||
360 | + } | ||
361 | + return null; | ||
362 | + } | ||
363 | + | ||
346 | @Override | 364 | @Override |
347 | public void setRole(Dpid dpid, RoleState role) { | 365 | public void setRole(Dpid dpid, RoleState role) { |
348 | final OpenFlowSwitch sw = getSwitch(dpid); | 366 | final OpenFlowSwitch sw = getSwitch(dpid); | ... | ... |
... | @@ -15,6 +15,8 @@ | ... | @@ -15,6 +15,8 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.provider.of.device.impl; | 16 | package org.onosproject.provider.of.device.impl; |
17 | 17 | ||
18 | +import com.google.common.collect.Maps; | ||
19 | +import com.google.common.collect.Sets; | ||
18 | import org.apache.felix.scr.annotations.Activate; | 20 | import org.apache.felix.scr.annotations.Activate; |
19 | import org.apache.felix.scr.annotations.Component; | 21 | import org.apache.felix.scr.annotations.Component; |
20 | import org.apache.felix.scr.annotations.Deactivate; | 22 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -29,31 +31,43 @@ import org.onosproject.net.PortNumber; | ... | @@ -29,31 +31,43 @@ import org.onosproject.net.PortNumber; |
29 | import org.onosproject.net.SparseAnnotations; | 31 | import org.onosproject.net.SparseAnnotations; |
30 | import org.onosproject.net.device.DefaultDeviceDescription; | 32 | import org.onosproject.net.device.DefaultDeviceDescription; |
31 | import org.onosproject.net.device.DefaultPortDescription; | 33 | import org.onosproject.net.device.DefaultPortDescription; |
34 | +import org.onosproject.net.device.DefaultPortStatistics; | ||
32 | import org.onosproject.net.device.DeviceDescription; | 35 | import org.onosproject.net.device.DeviceDescription; |
33 | import org.onosproject.net.device.DeviceProvider; | 36 | import org.onosproject.net.device.DeviceProvider; |
34 | import org.onosproject.net.device.DeviceProviderRegistry; | 37 | import org.onosproject.net.device.DeviceProviderRegistry; |
35 | import org.onosproject.net.device.DeviceProviderService; | 38 | import org.onosproject.net.device.DeviceProviderService; |
36 | import org.onosproject.net.device.PortDescription; | 39 | import org.onosproject.net.device.PortDescription; |
40 | +import org.onosproject.net.device.PortStatistics; | ||
37 | import org.onosproject.net.provider.AbstractProvider; | 41 | import org.onosproject.net.provider.AbstractProvider; |
38 | import org.onosproject.net.provider.ProviderId; | 42 | import org.onosproject.net.provider.ProviderId; |
39 | import org.onosproject.openflow.controller.Dpid; | 43 | import org.onosproject.openflow.controller.Dpid; |
40 | import org.onosproject.openflow.controller.OpenFlowController; | 44 | import org.onosproject.openflow.controller.OpenFlowController; |
45 | +import org.onosproject.openflow.controller.OpenFlowEventListener; | ||
41 | import org.onosproject.openflow.controller.OpenFlowSwitch; | 46 | import org.onosproject.openflow.controller.OpenFlowSwitch; |
42 | import org.onosproject.openflow.controller.OpenFlowSwitchListener; | 47 | import org.onosproject.openflow.controller.OpenFlowSwitchListener; |
43 | import org.onosproject.openflow.controller.RoleState; | 48 | import org.onosproject.openflow.controller.RoleState; |
44 | import org.onlab.packet.ChassisId; | 49 | import org.onlab.packet.ChassisId; |
45 | import org.projectfloodlight.openflow.protocol.OFFactory; | 50 | import org.projectfloodlight.openflow.protocol.OFFactory; |
51 | +import org.projectfloodlight.openflow.protocol.OFMessage; | ||
46 | import org.projectfloodlight.openflow.protocol.OFPortConfig; | 52 | import org.projectfloodlight.openflow.protocol.OFPortConfig; |
47 | import org.projectfloodlight.openflow.protocol.OFPortDesc; | 53 | import org.projectfloodlight.openflow.protocol.OFPortDesc; |
48 | import org.projectfloodlight.openflow.protocol.OFPortFeatures; | 54 | import org.projectfloodlight.openflow.protocol.OFPortFeatures; |
49 | import org.projectfloodlight.openflow.protocol.OFPortReason; | 55 | import org.projectfloodlight.openflow.protocol.OFPortReason; |
50 | import org.projectfloodlight.openflow.protocol.OFPortState; | 56 | import org.projectfloodlight.openflow.protocol.OFPortState; |
57 | +import org.projectfloodlight.openflow.protocol.OFPortStatsEntry; | ||
58 | +import org.projectfloodlight.openflow.protocol.OFPortStatsReply; | ||
51 | import org.projectfloodlight.openflow.protocol.OFPortStatus; | 59 | import org.projectfloodlight.openflow.protocol.OFPortStatus; |
60 | +import org.projectfloodlight.openflow.protocol.OFStatsReply; | ||
61 | +import org.projectfloodlight.openflow.protocol.OFStatsType; | ||
52 | import org.projectfloodlight.openflow.protocol.OFVersion; | 62 | import org.projectfloodlight.openflow.protocol.OFVersion; |
53 | import org.projectfloodlight.openflow.types.PortSpeed; | 63 | import org.projectfloodlight.openflow.types.PortSpeed; |
54 | import org.slf4j.Logger; | 64 | import org.slf4j.Logger; |
55 | 65 | ||
56 | import java.util.ArrayList; | 66 | import java.util.ArrayList; |
67 | +import java.util.Collection; | ||
68 | +import java.util.Collections; | ||
69 | +import java.util.HashMap; | ||
70 | +import java.util.HashSet; | ||
57 | import java.util.List; | 71 | import java.util.List; |
58 | 72 | ||
59 | import com.google.common.base.Strings; | 73 | import com.google.common.base.Strings; |
... | @@ -83,7 +97,12 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr | ... | @@ -83,7 +97,12 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr |
83 | 97 | ||
84 | private DeviceProviderService providerService; | 98 | private DeviceProviderService providerService; |
85 | 99 | ||
86 | - private final OpenFlowSwitchListener listener = new InternalDeviceProvider(); | 100 | + private final InternalDeviceProvider listener = new InternalDeviceProvider(); |
101 | + | ||
102 | + // TODO: We need to make the poll interval configurable. | ||
103 | + static final int POLL_INTERVAL = 10; | ||
104 | + | ||
105 | + private HashMap<Dpid, PortStatsCollector> collectors = Maps.newHashMap(); | ||
87 | 106 | ||
88 | /** | 107 | /** |
89 | * Creates an OpenFlow device provider. | 108 | * Creates an OpenFlow device provider. |
... | @@ -96,6 +115,7 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr | ... | @@ -96,6 +115,7 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr |
96 | public void activate() { | 115 | public void activate() { |
97 | providerService = providerRegistry.register(this); | 116 | providerService = providerRegistry.register(this); |
98 | controller.addListener(listener); | 117 | controller.addListener(listener); |
118 | + controller.addEventListener(listener); | ||
99 | for (OpenFlowSwitch sw : controller.getSwitches()) { | 119 | for (OpenFlowSwitch sw : controller.getSwitches()) { |
100 | try { | 120 | try { |
101 | listener.switchAdded(new Dpid(sw.getId())); | 121 | listener.switchAdded(new Dpid(sw.getId())); |
... | @@ -105,6 +125,9 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr | ... | @@ -105,6 +125,9 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr |
105 | // disconnect to trigger switch-add later | 125 | // disconnect to trigger switch-add later |
106 | sw.disconnectSwitch(); | 126 | sw.disconnectSwitch(); |
107 | } | 127 | } |
128 | + PortStatsCollector psc = new PortStatsCollector(sw, POLL_INTERVAL); | ||
129 | + psc.start(); | ||
130 | + collectors.put(new Dpid(sw.getId()), psc); | ||
108 | } | 131 | } |
109 | LOG.info("Started"); | 132 | LOG.info("Started"); |
110 | } | 133 | } |
... | @@ -174,7 +197,45 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr | ... | @@ -174,7 +197,45 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr |
174 | LOG.info("Accepting mastership role change for device {}", deviceId); | 197 | LOG.info("Accepting mastership role change for device {}", deviceId); |
175 | } | 198 | } |
176 | 199 | ||
177 | - private class InternalDeviceProvider implements OpenFlowSwitchListener { | 200 | + private void pushPortMetrics(Dpid dpid, OFPortStatsReply msg) { |
201 | + DeviceId deviceId = DeviceId.deviceId(dpid.uri(dpid)); | ||
202 | + | ||
203 | + Collection<PortStatistics> stats = buildPortStatistics(deviceId, msg); | ||
204 | + | ||
205 | + providerService.updatePortStatistics(deviceId, stats); | ||
206 | + } | ||
207 | + | ||
208 | + private Collection<PortStatistics> buildPortStatistics(DeviceId deviceId, OFPortStatsReply msg) { | ||
209 | + | ||
210 | + HashSet<PortStatistics> stats = Sets.newHashSet(); | ||
211 | + | ||
212 | + for (OFPortStatsEntry entry: msg.getEntries()) { | ||
213 | + if (entry.getPortNo().getPortNumber() < 0) { | ||
214 | + continue; | ||
215 | + } | ||
216 | + DefaultPortStatistics.Builder builder = DefaultPortStatistics.builder(); | ||
217 | + DefaultPortStatistics stat = builder.setDeviceId(deviceId) | ||
218 | + .setPort(entry.getPortNo().getPortNumber()) | ||
219 | + .setPacketsReceived(entry.getRxPackets().getValue()) | ||
220 | + .setPacketsSent(entry.getTxPackets().getValue()) | ||
221 | + .setBytesReceived(entry.getRxBytes().getValue()) | ||
222 | + .setBytesSent(entry.getTxBytes().getValue()) | ||
223 | + .setPacketsRxDropped(entry.getRxDropped().getValue()) | ||
224 | + .setPacketsTxDropped(entry.getTxDropped().getValue()) | ||
225 | + .setPacketsRxErrors(entry.getRxErrors().getValue()) | ||
226 | + .setPacketsTxErrors(entry.getTxErrors().getValue()) | ||
227 | + .setDurationSec(entry.getDurationSec()) | ||
228 | + .setDurationNano(entry.getDurationNsec()) | ||
229 | + .build(); | ||
230 | + | ||
231 | + stats.add(stat); | ||
232 | + } | ||
233 | + | ||
234 | + return Collections.unmodifiableSet(stats); | ||
235 | + | ||
236 | + } | ||
237 | + | ||
238 | + private class InternalDeviceProvider implements OpenFlowSwitchListener, OpenFlowEventListener { | ||
178 | @Override | 239 | @Override |
179 | public void switchAdded(Dpid dpid) { | 240 | public void switchAdded(Dpid dpid) { |
180 | if (providerService == null) { | 241 | if (providerService == null) { |
... | @@ -201,6 +262,11 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr | ... | @@ -201,6 +262,11 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr |
201 | cId, annotations); | 262 | cId, annotations); |
202 | providerService.deviceConnected(did, description); | 263 | providerService.deviceConnected(did, description); |
203 | providerService.updatePorts(did, buildPortDescriptions(sw.getPorts())); | 264 | providerService.updatePorts(did, buildPortDescriptions(sw.getPorts())); |
265 | + | ||
266 | + PortStatsCollector psc = new PortStatsCollector( | ||
267 | + controller.getSwitch(dpid), POLL_INTERVAL); | ||
268 | + psc.start(); | ||
269 | + collectors.put(dpid, psc); | ||
204 | } | 270 | } |
205 | 271 | ||
206 | @Override | 272 | @Override |
... | @@ -209,8 +275,12 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr | ... | @@ -209,8 +275,12 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr |
209 | return; | 275 | return; |
210 | } | 276 | } |
211 | providerService.deviceDisconnected(deviceId(uri(dpid))); | 277 | providerService.deviceDisconnected(deviceId(uri(dpid))); |
212 | - } | ||
213 | 278 | ||
279 | + PortStatsCollector collector = collectors.remove(dpid); | ||
280 | + if (collector != null) { | ||
281 | + collector.stop(); | ||
282 | + } | ||
283 | + } | ||
214 | 284 | ||
215 | @Override | 285 | @Override |
216 | public void switchChanged(Dpid dpid) { | 286 | public void switchChanged(Dpid dpid) { |
... | @@ -328,6 +398,19 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr | ... | @@ -328,6 +398,19 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr |
328 | } | 398 | } |
329 | return portSpeed.getSpeedBps() / MBPS; | 399 | return portSpeed.getSpeedBps() / MBPS; |
330 | } | 400 | } |
401 | + | ||
402 | + @Override | ||
403 | + public void handleMessage(Dpid dpid, OFMessage msg) { | ||
404 | + switch (msg.getType()) { | ||
405 | + case STATS_REPLY: | ||
406 | + if (((OFStatsReply) msg).getStatsType() == OFStatsType.PORT) { | ||
407 | + pushPortMetrics(dpid, (OFPortStatsReply) msg); | ||
408 | + } | ||
409 | + break; | ||
410 | + default: | ||
411 | + break; | ||
412 | + } | ||
413 | + } | ||
331 | } | 414 | } |
332 | 415 | ||
333 | } | 416 | } | ... | ... |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
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 | + | ||
17 | +package org.onosproject.provider.of.device.impl; | ||
18 | + | ||
19 | +import org.jboss.netty.util.HashedWheelTimer; | ||
20 | +import org.jboss.netty.util.Timeout; | ||
21 | +import org.jboss.netty.util.TimerTask; | ||
22 | +import org.onlab.util.Timer; | ||
23 | +import org.onosproject.openflow.controller.OpenFlowSwitch; | ||
24 | +import org.onosproject.openflow.controller.RoleState; | ||
25 | +import org.projectfloodlight.openflow.protocol.OFPortStatsRequest; | ||
26 | +import org.projectfloodlight.openflow.types.OFPort; | ||
27 | +import org.slf4j.Logger; | ||
28 | + | ||
29 | +import java.util.concurrent.TimeUnit; | ||
30 | +import java.util.concurrent.atomic.AtomicLong; | ||
31 | + | ||
32 | +import static org.slf4j.LoggerFactory.getLogger; | ||
33 | + | ||
34 | +/* | ||
35 | + * Sends Group Stats Request and collect the group statistics with a time interval. | ||
36 | + */ | ||
37 | +public class PortStatsCollector implements TimerTask { | ||
38 | + | ||
39 | + // TODO: Refactoring is required using ScheduledExecutorService | ||
40 | + | ||
41 | + private final HashedWheelTimer timer = Timer.getTimer(); | ||
42 | + private final OpenFlowSwitch sw; | ||
43 | + private final Logger log = getLogger(getClass()); | ||
44 | + private final int refreshInterval; | ||
45 | + private final AtomicLong xidAtomic = new AtomicLong(1); | ||
46 | + | ||
47 | + private Timeout timeout; | ||
48 | + | ||
49 | + private boolean stopTimer = false; | ||
50 | + | ||
51 | + /** | ||
52 | + * Creates a GroupStatsCollector object. | ||
53 | + * | ||
54 | + * @param sw Open Flow switch | ||
55 | + * @param interval time interval for collecting group statistic | ||
56 | + */ | ||
57 | + public PortStatsCollector(OpenFlowSwitch sw, int interval) { | ||
58 | + this.sw = sw; | ||
59 | + this.refreshInterval = interval; | ||
60 | + } | ||
61 | + | ||
62 | + @Override | ||
63 | + public void run(Timeout timeout) throws Exception { | ||
64 | + log.trace("Collecting stats for {}", sw.getStringId()); | ||
65 | + | ||
66 | + sendPortStatistic(); | ||
67 | + | ||
68 | + if (!this.stopTimer) { | ||
69 | + log.trace("Scheduling stats collection in {} seconds for {}", | ||
70 | + this.refreshInterval, this.sw.getStringId()); | ||
71 | + timeout.getTimer().newTimeout(this, refreshInterval, | ||
72 | + TimeUnit.SECONDS); | ||
73 | + } | ||
74 | + } | ||
75 | + | ||
76 | + private void sendPortStatistic() { | ||
77 | + if (log.isTraceEnabled()) { | ||
78 | + log.trace("sendGroupStatistics {}:{}", sw.getStringId(), sw.getRole()); | ||
79 | + } | ||
80 | + if (sw.getRole() != RoleState.MASTER) { | ||
81 | + return; | ||
82 | + } | ||
83 | + Long statsXid = xidAtomic.getAndIncrement(); | ||
84 | + OFPortStatsRequest statsRequest = sw.factory().buildPortStatsRequest() | ||
85 | + .setPortNo(OFPort.ANY) | ||
86 | + .setXid(statsXid) | ||
87 | + .build(); | ||
88 | + sw.sendMsg(statsRequest); | ||
89 | + } | ||
90 | + | ||
91 | + /** | ||
92 | + * Starts the collector. | ||
93 | + */ | ||
94 | + public void start() { | ||
95 | + log.info("Starting Port Stats collection thread for {}", sw.getStringId()); | ||
96 | + timeout = timer.newTimeout(this, 1, TimeUnit.SECONDS); | ||
97 | + } | ||
98 | + | ||
99 | + /** | ||
100 | + * Stops the collector. | ||
101 | + */ | ||
102 | + public void stop() { | ||
103 | + log.info("Stopping Port Stats collection thread for {}", sw.getStringId()); | ||
104 | + this.stopTimer = true; | ||
105 | + timeout.cancel(); | ||
106 | + } | ||
107 | +} |
... | @@ -23,6 +23,7 @@ import static org.onosproject.net.Device.Type.*; | ... | @@ -23,6 +23,7 @@ import static org.onosproject.net.Device.Type.*; |
23 | import static org.onosproject.net.MastershipRole.*; | 23 | import static org.onosproject.net.MastershipRole.*; |
24 | 24 | ||
25 | import java.util.ArrayList; | 25 | import java.util.ArrayList; |
26 | +import java.util.Collection; | ||
26 | import java.util.HashMap; | 27 | import java.util.HashMap; |
27 | import java.util.HashSet; | 28 | import java.util.HashSet; |
28 | import java.util.List; | 29 | import java.util.List; |
... | @@ -41,6 +42,7 @@ import org.onosproject.net.device.DeviceProvider; | ... | @@ -41,6 +42,7 @@ import org.onosproject.net.device.DeviceProvider; |
41 | import org.onosproject.net.device.DeviceProviderRegistry; | 42 | import org.onosproject.net.device.DeviceProviderRegistry; |
42 | import org.onosproject.net.device.DeviceProviderService; | 43 | import org.onosproject.net.device.DeviceProviderService; |
43 | import org.onosproject.net.device.PortDescription; | 44 | import org.onosproject.net.device.PortDescription; |
45 | +import org.onosproject.net.device.PortStatistics; | ||
44 | import org.onosproject.net.provider.ProviderId; | 46 | import org.onosproject.net.provider.ProviderId; |
45 | import org.onosproject.openflow.controller.Dpid; | 47 | import org.onosproject.openflow.controller.Dpid; |
46 | import org.onosproject.openflow.controller.OpenFlowController; | 48 | import org.onosproject.openflow.controller.OpenFlowController; |
... | @@ -217,6 +219,11 @@ public class OpenFlowDeviceProviderTest { | ... | @@ -217,6 +219,11 @@ public class OpenFlowDeviceProviderTest { |
217 | roles.put(requested, Dpid.dpid(deviceId.uri())); | 219 | roles.put(requested, Dpid.dpid(deviceId.uri())); |
218 | } | 220 | } |
219 | 221 | ||
222 | + @Override | ||
223 | + public void updatePortStatistics(DeviceId deviceId, Collection<PortStatistics> portStatistics) { | ||
224 | + | ||
225 | + } | ||
226 | + | ||
220 | } | 227 | } |
221 | } | 228 | } |
222 | 229 | ... | ... |
-
Please register or login to post a comment