Commit a4351bc0 authored by Micha Mueller's avatar Micha Mueller
Browse files

WIP: Add plugin for Omni-path

parent 8e8ba433
;comments in config files are indicated by a semicolon
global {
mqttPrefix /FF112233445566778899AABBFFFF
;add here other global attributes for your plugin
}
sensorTemplates {
;define here template sensors
sensor temp1 {
interval 1000
minValues 3
pluginAtt 1234
}
}
sensors {
;define here the actual singleSensors for your plugin
sensor sens1 {
default temp1
mqttsuffix 0001
;add other attributes your plugin requires for a sensor
}
}
groups {
;define here the sensor groups for your plugin
group g1 {
;specify group attributes here
interval 1000
mqttprefix 01
;define sensors belonging to the group below
sensor gSens {
mqttsuffix 00
}
}
}
......@@ -19,7 +19,7 @@ if [ "${enableGroups}" = true ]
then
echo "#include \"${PLUGIN_NAME}Attributes.h\"" >> ${PLUGIN_NAME}SingleSensor.h
echo "" >> ${PLUGIN_NAME}SingleSensor.h
echo "class ${PLUGIN_NAME}SingleSensor : public ${PLUGIN_NAME}SensorBase, public ${PLUGIN_NAME}Attributes public SingleSensor {" >> ${PLUGIN_NAME}SingleSensor.h
echo "class ${PLUGIN_NAME}SingleSensor : public ${PLUGIN_NAME}SensorBase, public ${PLUGIN_NAME}Attributes, public SingleSensor {" >> ${PLUGIN_NAME}SingleSensor.h
else
echo "" >> ${PLUGIN_NAME}SingleSensor.h
echo "class ${PLUGIN_NAME}SingleSensor : public ${PLUGIN_NAME}SensorBase, public SingleSensor {" >> ${PLUGIN_NAME}SingleSensor.h
......
#!/bin/sh
cat << EOF > ${PLUGIN_NAME}.conf
cat << EOF > ${PLUGIN_NAME_LWC}.conf
;comments in config files are indicated by a semicolon
global {
......@@ -32,7 +32,7 @@ EOF
if [ "${enableGroups}" = true ]
then
cat << EOF >> ${PLUGIN_NAME}.conf
cat << EOF >> ${PLUGIN_NAME_LWC}.conf
groups {
;define here the sensor groups for your plugin
......
/*
* OpaAttributes.h
*
* Created on: 10.09.2018
* Author: Micha Mueller
*/
#ifndef OPA_OPAATTRIBUTES_H_
#define OPA_OPAATTRIBUTES_H_
#include <opamgt/opamgt.h>
#include <opamgt/opamgt_pa.h>
#include <inttypes.h>
class OpaAttributes {
public:
OpaAttributes() :
_hfiNum(0),
_portNum(0) {
_port = nullptr;
_imageID = {0};
}
virtual ~OpaAttributes() {
if(_port) {
omgt_close_port(port);
}
}
int32_t getHfiNum() const { return _hfiNum; }
uint8_t getPortNum() const { return _portNum; }
void setHfiNum(int32_t hfiNum) { _hfiNum = hfiNum; }
void setPortNum(uint8_t portNum) { _portNum = portNum; }
protected:
int32_t _hfiNum;
uint8_t _portNum;
struct omgt_port * _port;
STL_PA_IMAGE_ID_DATA _imageID;
STL_PA_IMAGE_INFO_DATA _imageInfo;
};
#endif /* OPA_OPAATTRIBUTES_H_ */
/*
* OpaConfigurator.cpp
*
* Created on: 10.09.2018
* Author: Micha Mueller
*/
#include "OpaConfigurator.h"
OpaConfigurator::OpaConfigurator() {}
OpaConfigurator::~OpaConfigurator() {}
bool OpaConfigurator::derivedReadConfig(boost::property_tree::iptree& cfg) {
/*
* TODO
* If neccessary, read in other plugin specific stuff
*/
//read one sensor at a time
BOOST_FOREACH(boost::property_tree::iptree::value_type &sensor, cfg.get_child("sensors")) {
if (STRCMP(sensor, "sensor")) {
LOG(debug) << "Sensor \"" << sensor.second.data() << "\"";
if (!sensor.second.empty()) {
OpaSingleSensor* opaSensor = new OpaSingleSensor(sensor.second.data());
//first check if default sensor is given
boost::optional<boost::property_tree::iptree&> defaultS = sensor.second.get_child_optional("default");
if(defaultS) {
LOG(debug) << " Using \"" << defaultS.get().data() << "\" as default.";
sensorMap_t::iterator it = _templateSensors.find(defaultS.get().data());
if(it != _templateSensors.end()) {
*opaSensor = it->second;
opaSensor->setName(sensor.second.data());
} else {
LOG(warning) << "Template sensor \"" << defaultS.get().data() << "\" not found! Using standard values.";
}
}
//read remaining values
if(readSensorBase(*opaSensor, sensor.second)) {
_sensors.push_back(opaSensor);
} else {
LOG(warning) << " Sensor \"" << sensor.second.data() << "\" has bad values! Ignoring...";
}
}
}
}
//read groups
BOOST_FOREACH(boost::property_tree::iptree::value_type &group, cfg.get_child("groups")) {
if (STRCMP(group, "group")) {
LOG(debug) << "Group \"" << group.second.data() << "\"";
if (!group.second.empty()) {
OpaSensorGroup opaGroup = new OpaSensorGroup(group.second.data());
/*
* TODO
* Read in other plugin specific group attributes
*/
//read mqttPart if present
std::string mqttPart = "";
boost::optional<boost::property_tree::iptree&> mqtt = group.second.get_child_optional("mqttprefix");
if (mqtt) {
mqttPart = mqtt.get().data();
}
//read remaining values
if (!readSensorInterface(opaGroup, group.second)) {
LOG(warning) << " SensorGroup \"" << group.second.data() << "\" has bad values!";
}
//read sensors for this group
BOOST_FOREACH(boost::property_tree::iptree::value_type &val, group.second) {
if (STRCMP(val, "sensor")) {
LOG(debug) << "Sensor \"" << val.second.data() << "\"";
OpaSensorBase* opaSB = new OpaSensorBase(val.second.data());
if(readSensorBase(*opaSB, val.second)) {
opaSB->setMqtt(_mqttPrefix + mqttPart + opaSB->getMqtt());
LOG(debug) << " Sensor " << opaSB->getName() << " using MQTT-Topic " << opaSB->getMqtt();
opaGroup->pushBackSensor(opaSB);
} else {
LOG(warning) << " Sensor \"" << val.second.data() << "\" has bad values! Ignoring...";
}
}
}
_sensorGroups.push_back(opaGroup);
}
}
}
return true;
}
bool OpaConfigurator::derivedReadSensorBase(OpaSensorBase& sensor, boost::property_tree::iptree& config) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &val, config) {
/*
* TODO
* Read in plugin specific sensor attributes
*/
if (STRCMP(val, "mqttsuffix")) {
sensor.setMqtt(val.second.data());
/* Example code:
} else if (STRCMP(val, ("stringAttribute"))) {
sensor.setStringAttribute(val.second.data());
} else if (STRCMP(val, "intAttribute")) {
sensor.setIntAttribute(stoi(val.second.data())); */
}
}
/*
* TODO
* Print the read in values for debugging
*/
/*
LOG(debug) << " stringAtt: " << sensor.getStringAttribute();
LOG(debug) << " intAtt : " << sensor.getIntAttribute();
*/
return true;
}
/*
* OpaConfigurator.h
*
* Created on: 10.09.2018
* Author: Micha Mueller
*/
#ifndef OPA_OPACONFIGURATOR_H_
#define OPA_OPACONFIGURATOR_H_
#include "../../headers/ConfiguratorTemplate.h"
#include "OpaSensorGroup.h"
#include "OpaSingleSensor.h"
class OpaConfigurator : public ConfiguratorTemplate<OpaSensorBase, OpaSingleSensor> {
public:
OpaConfigurator();
virtual ~OpaConfigurator();
protected:
bool derivedReadConfig(boost::property_tree::iptree& cfg) override;
void derivedReReadConfig() override { /* nothing to overwrite */ }
void derivedSetGlobalSettings(const pluginSettings_t& pluginSettings) override { /* nothing to overwrite */ }
bool derivedReadSensorBase(OpaSensorBase& sensor, boost::property_tree::iptree& config) override;
};
extern "C" ConfiguratorInterface* create() {
return new OpaConfigurator;
}
extern "C" void destroy(ConfiguratorInterface* c) {
delete c;
}
#endif /* OPA_OPACONFIGURATOR_H_ */
/*
* OpaSensorBase.h
*
* Created on: 10.09.2018
* Author: Micha Mueller
*/
#ifndef OPA_OPASENSORBASE_H_
#define OPA_OPASENSORBASE_H_
#include "../../headers/SensorBase.h"
enum PORT_COUNTER_DATA {
portXmitData = 0,
portRcvData = 1,
portXmitPkts = 2,
portRcvPkts = 3,
portMulticastXmitPkts = 4,
portMulticastRcvPkts = 5,
localLinkIntegrityErrors = 6,
fmConfigErrors = 7,
portRcvErrors = 8,
excessiveBufferOverruns = 9,
portRcvConstraintErrors = 10,
portRcvSwitchRelayErrors = 11,
portXmitDiscards = 12,
portXmitConstraintErrors = 13,
portRcvRemotePhysicalErrors = 14,
swPortCongestion = 15,
portXmitWait = 16,
portRcvFECN = 17,
portRcvBECN = 18,
portXmitTimeCong = 19,
portXmitWastedBW = 20,
portXmitWaitData = 21,
portRcvBubble = 22,
portMarkFECN = 23,
linkErrorRecovery = 24,
linkDowned = 25,
uncorrectableErrors = 26,
};
class OpaSensorBase : virtual public SensorBase {
public:
OpaSensorBase(const std::string& name) :
SensorBase(name),
_counterData(-1) {}
virtual ~OpaSensorBase() {}
int getCounterData() const { return _counterData; }
void setCounterData(int counterData) { _counterData = counterData; }
protected:
PORT_COUNTER_DATA _counterData;
};
#endif /* OPA_OPASENSORBASE_H_ */
/*
* OpaSensorGroup.cpp
*
* Created on: 10.09.2018
* Author: Micha Mueller
*/
#include "OpaSensorGroup.h"
#include "timestamp.h"
OpaSensorGroup::OpaSensorGroup(const std::string name) :
SensorGroupTemplate(name) {}
OpaSensorGroup::~OpaSensorGroup() {}
void OpaSensorGroup::init(boost::asio::io_service& io) {
_cacheSize = _cacheInterval / _interval + 1;
_timer.reset(new boost::asio::deadline_timer(io, boost::posix_time::seconds(0)));
/*
* TODO
* Init plugin specific stuff
*/
for (auto s : _sensors) {
s->initSensor(_cacheSize);
}
}
void OpaSensorGroup::start() {
if (_keepRunning) {
//we have been started already
LOG(info) << "Sensorgroup " << _groupName << " already running.";
return;
}
/*
* TODO
* Start plugin specific stuff
*/
_keepRunning = 1;
_pendingTasks++;
_timer->async_wait(std::bind(&OpaSensorGroup::readAsync, this));
LOG(info) << "Sensorgroup " << _groupName << " started.";
}
void OpaSensorGroup::stop() {
_keepRunning = 0;
/*
* TODO
* Stop plugin specific stuff
*/
LOG(info) << "Sensorgroup " << _groupName << " stopped.";
}
void OpaSensorGroup::read() {
reading_t reading;
reading.timestamp = getTimestamp();
try {
for(auto s : _sensors) {
reading.value = /*
* TODO
* Read a value for every sensor affiliated with this group and store
* it with the appropriate sensor.
*/ 0;
s->storeReading(reading, _cacheIndex);
#ifdef DEBUG
LOG(debug) << _groupName << "::" << s->getName() << ": \"" << reading.value << "\"";
#endif
}
} catch (const std::exception& e) {
LOG(error) << "Sensorgroup" << _groupName << " could not read value";
return;
}
_cacheIndex = (_cacheIndex + 1) % _cacheSize;
}
void OpaSensorGroup::readAsync() {
uint64_t now = getTimestamp();
read();
if (_timer && _keepRunning) {
uint64_t next = now + MS_TO_NS(_interval);
_timer->expires_at(timestamp2ptime(next));
_pendingTasks++;
_timer->async_wait(std::bind(&OpaSensorGroup::readAsync, this));
}
_pendingTasks--;
}
/*
* OpaSensorGroup.h
*
* Created on: 10.09.2018
* Author: Micha Mueller
*/
#ifndef OPA_OPASENSORGROUP_H_
#define OPA_OPASENSORGROUP_H_
#include "../../headers/SensorGroupTemplate.h"
#include "OpaAttributes.h"
#include "OpaSensorBase.h"
class OpaSensorGroup : public SensorGroupTemplate<OpaSensorBase>, public OpaAttributes {
public:
OpaSensorGroup(const std::string name);
virtual ~OpaSensorGroup();
void init(boost::asio::io_service& io) override;
void start() override;
void stop() override;
private:
void read() override;
void readAsync() override;
};
#endif /* OPA_OPASENSORGROUP_H_ */
/*
* OpaSingleSensor.cpp
*
* Created on: 10.09.2018
* Author: Micha Mueller
*/
#include "OpaSingleSensor.h"
#include "timestamp.h"
OpaSingleSensor::OpaSingleSensor(const std::string& name) :
SensorBase(name), OpaSensorBase(name), SingleSensor(name) {}
OpaSingleSensor::~OpaSingleSensor() {}
void OpaSingleSensor::start() {
if (_keepRunning) {
//we have been started already
LOG(info) << "Sensor " << _name << " already running.";
return;
}
if (omgt_open_port_by_num(&_port, _hfiNum, _portNum, NULL) != OMGT_STATUS_SUCCESS) {
LOG(error) << "Sensor " << _name << " failed to open port or initialize PA connection";
_port = nullptr;
return;
}
if (omgt_pa_get_image_info(_port, _imageID, &_imageInfo)) {
LOG(error) << "Sensor " << _name << " failed to get PA image";
omgt_close_port(_port);
_port = nullptr;
return;
}
_keepRunning = 1;
_pendingTasks++;
_timer->async_wait(std::bind(&OpaSingleSensor::readAsync, this));
LOG(info) << "Sensor " << _name << " started.";
}
void OpaSingleSensor::stop() {
_keepRunning = 0;
if (_port) {
omgt_close_port(_port);
_port = nullptr;
}
LOG(info) << "Sensor " << _name << " stopped.";
}
void OpaSingleSensor::read() {
reading_t reading;
reading.timestamp = getTimestamp();
try {
STL_PORT_COUNTERS_DATA portCounters;
if (omgt_pa_get_port_stats(_port, _imageID, 1, _portNum, &_imageID, &portCounters, NULL, 0, 1)) {
throw std::runtime_error("Failed to get port counters");
}
switch(_counterData) {
case(portXmitData) :
reading.value = portCounters.portXmitData;
break;
case(portRcvData) :
reading.value = portCounters.portRcvData;
break;
case(portXmitPkts) :
reading.value = portCounters.portXmitPkts;
break;
case(portRcvPkts) :
reading.value = portCounters.portRcvPkts;
break;
case(portMulticastXmitPkts) :
reading.value = portCounters.portMulticastXmitPkts;
break;
case(portMulticastRcvPkts) :
reading.value = portCounters.portMulticastRcvPkts;
break;
case(localLinkIntegrityErrors) :
reading.value = portCounters.localLinkIntegrityErrors;
break;
case(fmConfigErrors) :
reading.value = portCounters.fmConfigErrors;
break;
case(portRcvErrors) :
reading.value = portCounters.portRcvErrors;
break;
case(excessiveBufferOverruns) :
reading.value = portCounters.excessiveBufferOverruns;
break;
case(portRcvConstraintErrors) :
reading.value = portCounters.portRcvConstraintErrors;
break;
case(portRcvSwitchRelayErrors) :
reading.value = portCounters.portRcvSwitchRelayErrors;
break;
case(portXmitDiscards) :
reading.value = portCounters.portXmitDiscards;
break;
case(portXmitConstraintErrors) :
reading.value = portCounters.portXmitConstraintErrors;
break;
case(portRcvRemotePhysicalErrors) :
reading.value = portCounters.portRcvRemotePhysicalErrors;
break;
case(swPortCongestion) :
reading.value = portCounters.swPortCongestion;
break;
case(portXmitWait) :
reading.value = portCounters.portXmitWait;
break;
case(portRcvFECN) :
reading.value = portCounters.portRcvFECN;
break;
case(portRcvBECN) :
reading.value = portCounters.portRcvBECN;
break;
case(portXmitTimeCong) :
reading.value = portCounters.portXmitTimeCong;
break;
case(portXmitWastedBW) :
reading.value = portCounters.portXmitWastedBW;
break;
case(portXmitWaitData) :
reading.value = portCounters.portXmitWaitData;
break;
case(portRcvBubble) :
reading.value = portCounters.portRcvBubble;
break;
case(portMarkFECN) :
reading.value = portCounters.portMarkFECN;
break;
case(linkErrorRecovery) :
reading.value = portCounters.linkErrorRecovery;
break;
case(linkDowned) :
reading.value = portCounters.linkDowned;
break;
case(uncorrectableErrors) :
reading.value = portCounters.uncorrectableErrors;
break;
default:
throw std::runtime_error("Unknown counter data");
break;
}