blob: 3f0a6fcb85cdd213e9c4a7e80578b31633ad9fbc [file] [log] [blame] [raw]
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "devreader-linux-sysfs-ib.h"
#include <fstream>
#include <string>
#include <list>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
LinuxSysFsInfiniBandDevReader::LinuxSysFsInfiniBandDevReader(const string& deviceName)
: DevReader(deviceName)
{
}
LinuxSysFsInfiniBandDevReader::~LinuxSysFsInfiniBandDevReader()
{
}
bool LinuxSysFsInfiniBandDevReader::isAvailable()
{
struct stat s;
return stat("/sys/class/infiniband", &s) == 0 && S_ISDIR(s.st_mode);
}
list<string> LinuxSysFsInfiniBandDevReader::findAllDevices() {
list<string> interfaceNames;
DIR *dir = opendir("/sys/class/infiniband");
if(!dir) return interfaceNames;
struct dirent *entry;
while((entry = readdir(dir))) {
if(entry->d_name[0] == '.') continue;
string dev_name(entry->d_name);
string path = "/sys/class/infiniband/" + dev_name + "/ports";
DIR *ports_dir = opendir(path.c_str());
struct dirent *ports_dir_entry;
while((ports_dir_entry = readdir(ports_dir))) {
if(ports_dir_entry->d_name[0] == '.') continue;
interfaceNames.push_back(dev_name + "p" + ports_dir_entry->d_name);
}
}
closedir(dir);
return interfaceNames;
}
static uint64_t read_uint64_plain_text(const string &entry) {
ifstream sysEntry(entry.c_str());
if(!sysEntry.is_open())
return 0;
uint64_t num = 0;
sysEntry >> num;
if(sysEntry.fail())
return 0;
return num;
}
static bool is_directory(const string &path) {
struct stat stat;
return ::stat(path.c_str(), &stat) == 0 && S_ISDIR(stat.st_mode);
}
void LinuxSysFsInfiniBandDevReader::readFromDevice(DataFrame &dataFrame) {
size_t port_i = m_deviceName.find_last_of('p');
if(port_i == string::npos) {
string path = "/sys/class/infiniband/" + m_deviceName + "/ports/";
if(!is_directory(path)) return;
uint64_t rx_bytes = 0;
uint64_t tx_bytes = 0;
uint64_t rx_packets = 0;
uint64_t tx_packets = 0;
uint64_t rx_errors = 0;
uint64_t tx_drops = 0;
DIR *dir = opendir(path.c_str());
struct dirent *dir_entry;
while((dir_entry = readdir(dir))) {
if(dir_entry->d_name[0] == '.') continue;
string counters_path = path + dir_entry->d_name + "/counters/";
rx_bytes += read_uint64_plain_text(counters_path + "port_rcv_data") * 4;
tx_bytes += read_uint64_plain_text(counters_path + "port_xmit_data") * 4;
rx_packets += read_uint64_plain_text(counters_path + "port_rcv_packets");
tx_packets += read_uint64_plain_text(counters_path + "port_xmit_packets");
rx_errors += read_uint64_plain_text(counters_path + "port_rcv_errors");
tx_drops += read_uint64_plain_text(counters_path + "port_xmit_discards");
}
closedir(dir);
dataFrame.setTotalDataIn(rx_bytes);
dataFrame.setTotalDataOut(tx_bytes);
dataFrame.setTotalPacketsIn(rx_packets);
dataFrame.setTotalPacketsOut(tx_packets);
dataFrame.setTotalErrorsIn(rx_errors);
dataFrame.setTotalDropsOut(tx_drops);
} else {
string path = "/sys/class/infiniband/" + m_deviceName.substr(0, port_i) +
"/ports/" + m_deviceName.substr(port_i + 1) + "/counters/";
if(!is_directory(path)) return;
dataFrame.setTotalDataIn(read_uint64_plain_text(path + "port_rcv_data") * 4);
dataFrame.setTotalDataOut(read_uint64_plain_text(path + "port_xmit_data") * 4);
dataFrame.setTotalPacketsIn(read_uint64_plain_text(path + "port_rcv_packets"));
dataFrame.setTotalPacketsOut(read_uint64_plain_text(path + "port_xmit_packets"));
dataFrame.setTotalErrorsIn(read_uint64_plain_text(path + "port_rcv_errors"));
dataFrame.setTotalDropsOut(read_uint64_plain_text(path + "port_xmit_discards"));
}
dataFrame.setValid(true);
}