1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* ArubaInstant.php |
4
|
|
|
* |
5
|
|
|
* HPE Aruba Instant |
6
|
|
|
* |
7
|
|
|
* |
8
|
|
|
* This program is free software: you can redistribute it and/or modify |
9
|
|
|
* it under the terms of the GNU General Public License as published by |
10
|
|
|
* the Free Software Foundation, either version 3 of the License, or |
11
|
|
|
* (at your option) any later version. |
12
|
|
|
* |
13
|
|
|
* This program is distributed in the hope that it will be useful, |
14
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
15
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the |
16
|
|
|
* GNU General Public License for more details. |
17
|
|
|
* |
18
|
|
|
* You should have received a copy of the GNU General Public License |
19
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. |
20
|
|
|
* |
21
|
|
|
* @link https://www.librenms.org |
22
|
|
|
* |
23
|
|
|
* @copyright 2019 Timothy Willey |
24
|
|
|
* @author Timothy Willey <[email protected]> |
25
|
|
|
*/ |
26
|
|
|
|
27
|
|
|
namespace LibreNMS\OS; |
28
|
|
|
|
29
|
|
|
use App\Models\Device; |
30
|
|
|
use LibreNMS\Device\Processor; |
31
|
|
|
use LibreNMS\Device\WirelessSensor; |
32
|
|
|
use LibreNMS\Interfaces\Discovery\OSDiscovery; |
33
|
|
|
use LibreNMS\Interfaces\Discovery\ProcessorDiscovery; |
34
|
|
|
use LibreNMS\Interfaces\Discovery\Sensors\WirelessApCountDiscovery; |
35
|
|
|
use LibreNMS\Interfaces\Discovery\Sensors\WirelessClientsDiscovery; |
36
|
|
|
use LibreNMS\Interfaces\Discovery\Sensors\WirelessFrequencyDiscovery; |
37
|
|
|
use LibreNMS\Interfaces\Discovery\Sensors\WirelessNoiseFloorDiscovery; |
38
|
|
|
use LibreNMS\Interfaces\Discovery\Sensors\WirelessPowerDiscovery; |
39
|
|
|
use LibreNMS\Interfaces\Discovery\Sensors\WirelessUtilizationDiscovery; |
40
|
|
|
use LibreNMS\Interfaces\Polling\Sensors\WirelessApCountPolling; |
41
|
|
|
use LibreNMS\Interfaces\Polling\Sensors\WirelessClientsPolling; |
42
|
|
|
use LibreNMS\Interfaces\Polling\Sensors\WirelessFrequencyPolling; |
43
|
|
|
use LibreNMS\OS; |
44
|
|
|
use LibreNMS\Util\Rewrite; |
45
|
|
|
|
46
|
|
|
class ArubaInstant extends OS implements |
47
|
|
|
OSDiscovery, |
48
|
|
|
ProcessorDiscovery, |
49
|
|
|
WirelessApCountDiscovery, |
50
|
|
|
WirelessApCountPolling, |
51
|
|
|
WirelessClientsDiscovery, |
52
|
|
|
WirelessClientsPolling, |
53
|
|
|
WirelessFrequencyDiscovery, |
54
|
|
|
WirelessFrequencyPolling, |
55
|
|
|
WirelessNoiseFloorDiscovery, |
56
|
|
|
WirelessPowerDiscovery, |
57
|
|
|
WirelessUtilizationDiscovery |
58
|
|
|
{ |
59
|
|
|
public function discoverOS(Device $device): void |
60
|
|
|
{ |
61
|
|
|
parent::discoverOS($device); // yaml |
62
|
|
|
$device->serial = snmp_getnext($this->getDeviceArray(), 'aiAPSerialNum', '-Oqv', 'AI-AP-MIB'); |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Discover processors. |
67
|
|
|
* Returns an array of LibreNMS\Device\Processor objects that have been discovered |
68
|
|
|
* |
69
|
|
|
* @return array Processors |
70
|
|
|
*/ |
71
|
|
|
public function discoverProcessors() |
72
|
|
|
{ |
73
|
|
|
$processors = []; |
74
|
|
|
$ai_mib = 'AI-AP-MIB'; |
75
|
|
|
$ai_ap_data = $this->getCacheTable('aiAccessPointEntry', $ai_mib); |
76
|
|
|
|
77
|
|
|
foreach ($ai_ap_data as $ai_ap => $ai_ap_oid) { |
78
|
|
|
$value = $ai_ap_oid['aiAPCPUUtilization']; |
79
|
|
|
$combined_oid = sprintf('%s::%s.%s', $ai_mib, 'aiAPCPUUtilization', Rewrite::oidMac($ai_ap)); |
80
|
|
|
$oid = snmp_translate($combined_oid, 'ALL', 'arubaos', '-On'); |
81
|
|
|
$description = $ai_ap_data[$ai_ap]['aiAPSerialNum']; |
82
|
|
|
$processors[] = Processor::discover('aruba-instant', $this->getDeviceId(), $oid, Rewrite::macToHex($ai_ap), $description, 1, $value); |
83
|
|
|
} // end foreach |
84
|
|
|
|
85
|
|
|
return $processors; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Discover wireless client counts. Type is clients. |
90
|
|
|
* Returns an array of LibreNMS\Device\Sensor objects that have been discovered |
91
|
|
|
* |
92
|
|
|
* @return array Sensors |
93
|
|
|
*/ |
94
|
|
|
public function discoverWirelessClients() |
95
|
|
|
{ |
96
|
|
|
$sensors = []; |
97
|
|
|
$device = $this->getDeviceArray(); |
98
|
|
|
$ai_mib = 'AI-AP-MIB'; |
99
|
|
|
|
100
|
|
|
if (intval(explode('.', $device['version'])[0]) >= 8 && intval(explode('.', $device['version'])[1]) >= 4) { |
101
|
|
|
// version is at least 8.4.0.0 |
102
|
|
|
$ssid_data = $this->getCacheTable('aiWlanSSIDEntry', $ai_mib); |
103
|
|
|
|
104
|
|
|
$ap_data = array_merge_recursive( |
105
|
|
|
$this->getCacheTable('aiAccessPointEntry', $ai_mib), |
|
|
|
|
106
|
|
|
$this->getCacheTable('aiRadioClientNum', $ai_mib) |
107
|
|
|
); |
108
|
|
|
|
109
|
|
|
$oids = []; |
110
|
|
|
$total_clients = 0; |
111
|
|
|
|
112
|
|
|
// Clients Per SSID |
113
|
|
|
foreach ($ssid_data as $index => $entry) { |
114
|
|
|
$combined_oid = sprintf('%s::%s.%s', $ai_mib, 'aiSSIDClientNum', $index); |
115
|
|
|
$oid = snmp_translate($combined_oid, 'ALL', 'arubaos', '-On'); |
116
|
|
|
$description = sprintf('SSID %s Clients', $entry['aiSSID']); |
117
|
|
|
$oids[] = $oid; |
118
|
|
|
$total_clients += $entry['aiSSIDClientNum']; |
119
|
|
|
$sensors[] = new WirelessSensor('clients', $this->getDeviceId(), $oid, 'aruba-instant', $index, $description, $entry['aiSSIDClientNum']); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
// Total Clients across all SSIDs |
123
|
|
|
$sensors[] = new WirelessSensor('clients', $this->getDeviceId(), $oids, 'aruba-instant', 'total-clients', 'Total Clients', $total_clients); |
124
|
|
|
|
125
|
|
|
// Clients Per Radio |
126
|
|
|
foreach ($ap_data as $index => $entry) { |
127
|
|
|
foreach ($entry['aiRadioClientNum'] as $radio => $value) { |
128
|
|
|
$combined_oid = sprintf('%s::%s.%s.%s', $ai_mib, 'aiRadioClientNum', Rewrite::oidMac($index), $radio); |
129
|
|
|
$oid = snmp_translate($combined_oid, 'ALL', 'arubaos', '-On'); |
130
|
|
|
$description = sprintf('%s Radio %s', $entry['aiAPSerialNum'], $radio); |
131
|
|
|
$sensor_index = sprintf('%s.%s', Rewrite::macToHex($index), $radio); |
132
|
|
|
$sensors[] = new WirelessSensor('clients', $this->getDeviceId(), $oid, 'aruba-instant', $sensor_index, $description, $value); |
133
|
|
|
} |
134
|
|
|
} |
135
|
|
|
} else { |
136
|
|
|
// version is lower than 8.4.0.0 |
137
|
|
|
// fetch the MAC addresses of currently connected clients, then count them to get an overall total |
138
|
|
|
$client_data = $this->getCacheTable('aiClientMACAddress', $ai_mib); |
139
|
|
|
|
140
|
|
|
$total_clients = sizeof($client_data); |
|
|
|
|
141
|
|
|
|
142
|
|
|
$combined_oid = sprintf('%s::%s', $ai_mib, 'aiClientMACAddress'); |
143
|
|
|
$oid = snmp_translate($combined_oid, 'ALL', 'arubaos', '-On'); |
144
|
|
|
|
145
|
|
|
$sensors[] = new WirelessSensor('clients', $this->getDeviceId(), $oid, 'aruba-instant', 'total-clients', 'Total Clients', $total_clients); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
return $sensors; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* Discover wireless AP counts. Type is ap-count. |
153
|
|
|
* Returns an array of LibreNMS\Device\Sensor objects that have been discovered |
154
|
|
|
* |
155
|
|
|
* @return array Sensors |
156
|
|
|
*/ |
157
|
|
|
public function discoverWirelessApCount() |
158
|
|
|
{ |
159
|
|
|
$sensors = []; |
160
|
|
|
$ai_mib = 'AI-AP-MIB'; |
161
|
|
|
$ap_data = $this->getCacheTable('aiAPSerialNum', $ai_mib); |
162
|
|
|
|
163
|
|
|
$total_aps = sizeof($ap_data); |
|
|
|
|
164
|
|
|
|
165
|
|
|
$combined_oid = sprintf('%s::%s', $ai_mib, 'aiAPSerialNum'); |
166
|
|
|
$oid = snmp_translate($combined_oid, 'ALL', 'arubaos', '-On'); |
167
|
|
|
|
168
|
|
|
$sensors[] = new WirelessSensor('ap-count', $this->getDeviceId(), $oid, 'aruba-instant', 'total-aps', 'Total APs', $total_aps); |
169
|
|
|
|
170
|
|
|
return $sensors; |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* Discover wireless frequency. This is in MHz. Type is frequency. |
175
|
|
|
* Returns an array of LibreNMS\Device\Sensor objects that have been discovered |
176
|
|
|
* |
177
|
|
|
* @return array Sensors |
178
|
|
|
*/ |
179
|
|
|
public function discoverWirelessFrequency() |
180
|
|
|
{ |
181
|
|
|
// instant |
182
|
|
|
return $this->discoverInstantRadio('frequency', 'aiRadioChannel'); |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* Discover wireless noise floor. This is in dBm/Hz. Type is noise-floor. |
187
|
|
|
* Returns an array of LibreNMS\Device\Sensor objects that have been discovered |
188
|
|
|
* |
189
|
|
|
* @return array |
190
|
|
|
*/ |
191
|
|
|
public function discoverWirelessNoiseFloor() |
192
|
|
|
{ |
193
|
|
|
// instant |
194
|
|
|
return $this->discoverInstantRadio('noise-floor', 'aiRadioNoiseFloor'); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* Discover wireless tx or rx power. This is in dBm. Type is power. |
199
|
|
|
* Returns an array of LibreNMS\Device\Sensor objects that have been discovered |
200
|
|
|
* |
201
|
|
|
* @return array |
202
|
|
|
*/ |
203
|
|
|
public function discoverWirelessPower() |
204
|
|
|
{ |
205
|
|
|
// instant |
206
|
|
|
return $this->discoverInstantRadio('power', 'aiRadioTransmitPower', '%s Radio %s: Tx Power'); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* Discover wireless utilization. This is in %. Type is utilization. |
211
|
|
|
* Returns an array of LibreNMS\Device\Sensor objects that have been discovered |
212
|
|
|
* |
213
|
|
|
* @return array Sensors |
214
|
|
|
*/ |
215
|
|
|
public function discoverWirelessUtilization() |
216
|
|
|
{ |
217
|
|
|
// instant |
218
|
|
|
return $this->discoverInstantRadio('utilization', 'aiRadioUtilization64'); |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
/** |
222
|
|
|
* Aruba Instant Radio Discovery |
223
|
|
|
* |
224
|
|
|
* @return array Sensors |
225
|
|
|
*/ |
226
|
|
|
private function discoverInstantRadio($type, $mib, $desc = '%s Radio %s') |
227
|
|
|
{ |
228
|
|
|
$ai_mib = 'AI-AP-MIB'; |
229
|
|
|
$ai_sg_data = array_merge_recursive( |
230
|
|
|
$this->getCacheTable('aiAPSerialNum', $ai_mib), |
|
|
|
|
231
|
|
|
$this->getCacheTable('aiRadioChannel', $ai_mib), |
232
|
|
|
$this->getCacheTable('aiRadioNoiseFloor', $ai_mib), |
233
|
|
|
$this->getCacheTable('aiRadioTransmitPower', $ai_mib), |
234
|
|
|
$this->getCacheTable('aiRadioUtilization64', $ai_mib) |
235
|
|
|
); |
236
|
|
|
|
237
|
|
|
$sensors = []; |
238
|
|
|
|
239
|
|
|
foreach ($ai_sg_data as $ai_ap => $ai_ap_oid) { |
240
|
|
|
if (isset($ai_ap_oid[$mib])) { |
241
|
|
|
foreach ($ai_ap_oid[$mib] as $ai_ap_radio => $value) { |
242
|
|
|
$multiplier = 1; |
243
|
|
|
if ($type == 'frequency') { |
244
|
|
|
$value = WirelessSensor::channelToFrequency($this->decodeChannel($value)); |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
if ($type == 'noise-floor') { |
248
|
|
|
$multiplier = -1; |
249
|
|
|
$value = $value * $multiplier; |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
$combined_oid = sprintf('%s::%s.%s.%s', $ai_mib, $mib, Rewrite::oidMac($ai_ap), $ai_ap_radio); |
253
|
|
|
$oid = snmp_translate($combined_oid, 'ALL', 'arubaos', '-On'); |
254
|
|
|
$description = sprintf($desc, $ai_sg_data[$ai_ap]['aiAPSerialNum'], $ai_ap_radio); |
255
|
|
|
$index = sprintf('%s.%s', Rewrite::macToHex($ai_ap), $ai_ap_radio); |
256
|
|
|
|
257
|
|
|
$sensors[] = new WirelessSensor($type, $this->getDeviceId(), $oid, 'aruba-instant', $index, $description, $value, $multiplier); |
258
|
|
|
} // end foreach |
259
|
|
|
} // end if |
260
|
|
|
} // end foreach |
261
|
|
|
|
262
|
|
|
return $sensors; |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
protected function decodeChannel($channel) |
266
|
|
|
{ |
267
|
|
|
return $channel & 255; // mask off the channel width information |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* Poll wireless frequency as MHz |
272
|
|
|
* The returned array should be sensor_id => value pairs |
273
|
|
|
* |
274
|
|
|
* @param array $sensors Array of sensors needed to be polled |
275
|
|
|
* @return array of polled data |
276
|
|
|
*/ |
277
|
|
|
public function pollWirelessFrequency(array $sensors) |
278
|
|
|
{ |
279
|
|
|
return $this->pollWirelessChannelAsFrequency($sensors, [$this, 'decodeChannel']); |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
/** |
283
|
|
|
* Poll wireless clients |
284
|
|
|
* The returned array should be sensor_id => value pairs |
285
|
|
|
* |
286
|
|
|
* @param array $sensors Array of sensors needed to be polled |
287
|
|
|
* @return array of polled data |
288
|
|
|
*/ |
289
|
|
|
public function pollWirelessClients(array $sensors) |
290
|
|
|
{ |
291
|
|
|
$data = []; |
292
|
|
|
if (! empty($sensors)) { |
293
|
|
|
$device = $this->getDeviceArray(); |
294
|
|
|
|
295
|
|
|
if (intval(explode('.', $device['version'])[0]) >= 8 && intval(explode('.', $device['version'])[1]) >= 4) { |
296
|
|
|
// version is at least 8.4.0.0 |
297
|
|
|
$oids = []; |
298
|
|
|
|
299
|
|
|
foreach ($sensors as $sensor) { |
300
|
|
|
$oids[$sensor['sensor_id']] = current($sensor['sensor_oids']); |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
$snmp_data = snmp_get_multi_oid($this->getDeviceArray(), $oids); |
304
|
|
|
|
305
|
|
|
foreach ($oids as $id => $oid) { |
306
|
|
|
$data[$id] = $snmp_data[$oid]; |
307
|
|
|
} |
308
|
|
|
} else { |
309
|
|
|
// version is lower than 8.4.0.0 |
310
|
|
|
if (! empty($sensors) && sizeof($sensors) == 1) { |
311
|
|
|
$ai_mib = 'AI-AP-MIB'; |
312
|
|
|
$client_data = $this->getCacheTable('aiClientMACAddress', $ai_mib); |
313
|
|
|
|
314
|
|
|
if (empty($client_data)) { |
315
|
|
|
$total_clients = 0; |
316
|
|
|
} else { |
317
|
|
|
$total_clients = sizeof($client_data); |
318
|
|
|
} |
319
|
|
|
|
320
|
|
|
$data[$sensors[0]['sensor_id']] = $total_clients; |
321
|
|
|
} |
322
|
|
|
} |
323
|
|
|
} |
324
|
|
|
|
325
|
|
|
return $data; |
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
/** |
329
|
|
|
* Poll AP Count |
330
|
|
|
* The returned array should be sensor_id => value pairs |
331
|
|
|
* |
332
|
|
|
* @param array $sensors Array of sensors needed to be polled |
333
|
|
|
* @return array of polled data |
334
|
|
|
*/ |
335
|
|
|
public function pollWirelessApCount(array $sensors) |
336
|
|
|
{ |
337
|
|
|
$data = []; |
338
|
|
|
if (! empty($sensors) && sizeof($sensors) == 1) { |
339
|
|
|
$ai_mib = 'AI-AP-MIB'; |
340
|
|
|
$ap_data = $this->getCacheTable('aiAPSerialNum', $ai_mib); |
341
|
|
|
|
342
|
|
|
$total_aps = 0; |
343
|
|
|
|
344
|
|
|
if (! empty($ap_data)) { |
345
|
|
|
$total_aps = sizeof($ap_data); |
346
|
|
|
} |
347
|
|
|
|
348
|
|
|
$data[$sensors[0]['sensor_id']] = $total_aps; |
349
|
|
|
} |
350
|
|
|
|
351
|
|
|
return $data; |
352
|
|
|
} |
353
|
|
|
} |
354
|
|
|
|