From 4b7058918ce176c56866a579895d63d2890c4cf8 Mon Sep 17 00:00:00 2001 From: dan-du-car Date: Tue, 7 Nov 2023 17:56:04 +0000 Subject: [PATCH] update snmp call --- src/tmx/TmxUtils/src/SNMPClient.cpp | 318 ++++++++++++++++++ src/tmx/TmxUtils/src/SNMPClient.h | 116 +++++++ src/tmx/TmxUtils/src/SNMPClientException.cpp | 8 + src/tmx/TmxUtils/src/SNMPClientException.h | 23 ++ .../RSUHealthMonitorPlugin/CMakeLists.txt | 2 +- .../RSUHealthMonitorPlugin/manifest.json | 2 +- .../src/RSUHealthMonitorPlugin.cpp | 50 ++- .../src/RSUHealthMonitorPlugin.h | 6 +- 8 files changed, 516 insertions(+), 9 deletions(-) create mode 100644 src/tmx/TmxUtils/src/SNMPClient.cpp create mode 100644 src/tmx/TmxUtils/src/SNMPClient.h create mode 100644 src/tmx/TmxUtils/src/SNMPClientException.cpp create mode 100644 src/tmx/TmxUtils/src/SNMPClientException.h diff --git a/src/tmx/TmxUtils/src/SNMPClient.cpp b/src/tmx/TmxUtils/src/SNMPClient.cpp new file mode 100644 index 000000000..857c41692 --- /dev/null +++ b/src/tmx/TmxUtils/src/SNMPClient.cpp @@ -0,0 +1,318 @@ +#include "SNMPClient.h" + +namespace tmx::utils { + + // Client defaults to SNMPv3 + snmp_client::snmp_client(const std::string& ip, const int& port, const std::string& community, + const std::string &snmp_user, const std::string &securityLevel, const std::string &authPassPhrase, int snmp_version, int timeout) + + : ip_(ip), port_(port), community_(community),snmp_version_(snmp_version), timeout_(timeout) + { + + PLOG(logDEBUG1) << "Starting SNMP Client"; + PLOG(logDEBUG1) << "Target device IP address: " << ip_; + PLOG(logINFO) << "Target device NTCIP port: " << port_; + + // Bring the IP address and port of the target SNMP device in the required form, which is "IPADDRESS:PORT": + std::string ip_port_string = ip_ + ":" + std::to_string(port_); + char* ip_port = &ip_port_string[0]; + + // Initialize SNMP session parameters + init_snmp("carma_snmp"); + snmp_sess_init(&session); + session.peername = ip_port; + session.version = snmp_version_; // SNMP_VERSION_3 + session.securityName = (char *)snmp_user.c_str(); + session.securityNameLen = snmp_user.length(); + + session.securityModel = USM_SEC_MODEL_NUMBER; + + // Fallback behavior to setup a community for SNMP V1/V2 + if(snmp_version_ != 3){ + char community_char[community_.length()]; + std::copy(community_.begin(), community_.end(), community_char); + unsigned char* comm = reinterpret_cast(community_char); + + session.community = comm; + session.community_len = community_.length(); + } + + // SNMP authorization/privach config + if (securityLevel == "authPriv") { + session.securityLevel = SNMP_SEC_LEVEL_AUTHPRIV; + } + + else if (securityLevel == "authNoPriv") { + session.securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV; + } + + else session.securityLevel = SNMP_SEC_LEVEL_NOAUTH; + + // Passphrase used for both authentication and privacy + auto phrase_len = authPassPhrase.length(); + auto phrase = (u_char *) authPassPhrase.c_str(); + + // Defining and generating auth config with SHA1 + session.securityAuthProto = usmHMACSHA1AuthProtocol; + session.securityAuthProtoLen = USM_AUTH_PROTO_SHA_LEN; + session.securityAuthKeyLen = USM_AUTH_KU_LEN; + + if (generate_Ku(session.securityAuthProto, + session.securityAuthProtoLen, + phrase,phrase_len, + session.securityAuthKey, + &session.securityAuthKeyLen) != SNMPERR_SUCCESS) + { + std::string errMsg = "Error generating Ku from authentication pass phrase. \n"; + throw snmp_client_exception(errMsg); + } + + // Defining and generating priv config with AES (since using SHA1) + session.securityPrivProto = usmAESPrivProtocol; + session.securityAuthProtoLen = USM_PRIV_PROTO_AES_LEN; + session.securityPrivKeyLen = USM_PRIV_KU_LEN; + + if (generate_Ku(session.securityAuthProto, + session.securityAuthProtoLen, + phrase,phrase_len, + session.securityPrivKey, + &session.securityPrivKeyLen) != SNMPERR_SUCCESS) + { + std::string errMsg = "Error generating Ku from privacy pass phrase. \n"; + throw snmp_client_exception(errMsg); + } + + + session.timeout = timeout_; + + // Opens the snmp session if it exists + ss = snmp_open(&session); + + if (ss == nullptr) + { + PLOG(logERROR) << "Failed to establish session with target device"; + snmp_sess_perror("snmpget", &session); + throw snmp_client_exception("Failed to establish session with target device"); + } + else + { + PLOG(logINFO) << "Established session with device at " << ip_; + } + + } + + snmp_client::~snmp_client(){ + PLOG(logINFO) << "Closing SNMP session"; + snmp_close(ss); + } + + + // Original implementation used in Carma Streets https://github.com/usdot-fhwa-stol/snmp-client + bool snmp_client::process_snmp_request(const std::string& input_oid, const request_type& request_type, snmp_response_obj& val){ + + + /*Structure to hold response from the remote host*/ + snmp_pdu *response; + + // Create pdu for the data + if (request_type == request_type::GET) + { + PLOG(logDEBUG1) << "Attempting to GET value for: " << input_oid; + pdu = snmp_pdu_create(SNMP_MSG_GET); + } + else if (request_type == request_type::SET) + { + PLOG(logDEBUG1) << "Attempting to SET value for " << input_oid << " to " << val.val_int; + pdu = snmp_pdu_create(SNMP_MSG_SET); + } + else{ + PLOG(logERROR) << "Invalid request type, method accpets only GET and SET"; + } + + // Read input OID into an OID variable: + // net-snmp has several methods for creating an OID object + // their documentation suggests using get_node. read_objid seems like a simpler approach + // TO DO: investigate update to get_node + if(!read_objid(input_oid.c_str(), OID, &OID_len)){ + // If oid cannot be created + PLOG(logERROR) << "OID could not be created from input: " << input_oid; + return false; + + } + else{ + + if(request_type == request_type::GET) + { + // Add OID to pdu for get request + snmp_add_null_var(pdu, OID, OID_len); + } + else if(request_type == request_type::SET) + { + if(val.type == snmp_response_obj::response_type::INTEGER){ + snmp_add_var(pdu, OID, OID_len, 'i', (std::to_string(val.val_int)).c_str()); + } + // Needs to be finalized to support octet string use + else if(val.type == snmp_response_obj::response_type::STRING){ + PLOG(logERROR) << "Setting string value is currently not supported"; + // std::string str_input(val.val_string.begin(), val.val_string.end()); + // snmp_add_var(pdu, OID, OID_len, 's', str_input.c_str()); + // return false; + } + } + + PLOG(logERROR) << "Created OID for input: " << input_oid; + } + // Send the request + int status = snmp_synch_response(ss, pdu, &response); + PLOG(logDEBUG) << "Response request status: " << status; + + // Check response + if(status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) { + + PLOG(logINFO) << "STAT_SUCCESS, received a response"; + + if(request_type == request_type::GET){ + for(auto vars = response->variables; vars; vars = vars->next_variable){ + // Get value of variable depending on ASN.1 type + // Variable could be a integer, string, bitstring, ojbid, counter : defined here https://github.com/net-snmp/net-snmp/blob/master/include/net-snmp/types.h + // get Integer value + if(vars->type == ASN_INTEGER){ + if(vars->val.integer){ + val.val_int = *vars->val.integer; + PLOG(logDEBUG1) << "Integer value in object: " << val.val_int; + } + else{ + PLOG(logERROR) << "Response specifies type integer, but no integer value found"; + return false; + } + + } + else if(vars->type == ASN_OCTET_STR){ + if(vars->val.string){ + size_t str_len = vars->val_len; + for(size_t i = 0; i < str_len; ++i) + { + val.val_string.push_back(vars->val.string[i]); + } + + } + else{ + PLOG(logERROR) << "Response specifies type string, but no string value found"; + return false; + } + } + else{ + PLOG(logERROR) << "Received a message type which isn't an integer or string"; + return false; + } + } + } + else if(request_type == request_type::SET){ + + if(val.type == snmp_response_obj::response_type::INTEGER){ + PLOG(logDEBUG1) << "Success in SET for OID: " << input_oid << " Value: " << val.val_int; + } + + else if(val.type == snmp_response_obj::response_type::STRING){ + PLOG(logDEBUG1) << "Success in SET for OID: " << input_oid << " Value: "; + for(auto data : val.val_string){ + PLOG(logDEBUG1) << data; + } + } + } + + } + else + { + log_error(status, request_type, response); + return false; + } + + if (response){ + snmp_free_pdu(response); + OID_len = MAX_OID_LEN; + } + + return true; + } + + // Backup GET function for use with prexisting ERVCloudForwarding client + std::string snmp_client::SNMPGet(const std::string &req_oid) + { + snmp_pdu *response; + + std::string result = ""; + auto pdu = snmp_pdu_create(SNMP_MSG_GET); + + if (!snmp_parse_oid(req_oid.c_str(), OID, &OID_len)) + { + snmp_perror(req_oid.c_str()); + std::string errMsg = "OID could not be created from input:" + req_oid; + throw snmp_client_exception(errMsg); + SOCK_CLEANUP; + } + + snmp_add_null_var(pdu, OID, OID_len); + int status = snmp_synch_response(ss, pdu, &response); + + if (!response) + { + throw snmp_client_exception("No response for SNMP Get request!"); + } + else if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) + { + // SUCCESS: Return the response as result + for (auto vars = response->variables; vars; vars = vars->next_variable) + { + if (vars->type == ASN_OCTET_STR) + { + result = reinterpret_cast(vars->val.string); + } + else + { + throw snmp_client_exception("Received respones type is not a string"); + } + } + } + else + { + // FAILURE: Print what went wrong! + std::string errMsg = snmp_errstring(response->errstat); + throw snmp_client_exception("Error in packet. Reason:" + errMsg); + } + if (response) + snmp_free_pdu(response); + return result; + } + + + int snmp_client::get_port() const + { + return port_; + } + + + void snmp_client::log_error(const int& status, const request_type& request_type, snmp_pdu *response) const + { + + if (status == STAT_SUCCESS) + { + PLOG(logERROR) << "Variable type: " << response->variables->type; + PLOG(logERROR) << "Error in packet " << static_cast(snmp_errstring(static_cast(response->errstat))); + } + else if (status == STAT_TIMEOUT){ + + PLOG(logERROR) << "Timeout, no response from server"; + } + else{ + if(request_type == request_type::GET){ + PLOG(logERROR) << "Unknown SNMP Error for GET"; + } + else if(request_type == request_type::SET){ + PLOG(logERROR) << "Unknown SNMP Error for SET"; + } + } + + } + +} // namespace \ No newline at end of file diff --git a/src/tmx/TmxUtils/src/SNMPClient.h b/src/tmx/TmxUtils/src/SNMPClient.h new file mode 100644 index 000000000..7231d489f --- /dev/null +++ b/src/tmx/TmxUtils/src/SNMPClient.h @@ -0,0 +1,116 @@ +#pragma once + +#include +#include +#include +#include "PluginLog.h" + +#include "SNMPClientException.h" + +namespace tmx::utils { + +enum class request_type +{ + GET, + SET, + OTHER //Processing this request type is not a defined behavior, included for testing only +}; + + +/** @brief A struct to hold the value being sent to the TSC, can be integer or string. Type needs to be defined*/ +struct snmp_response_obj +{ + /** @brief The type of value being requested or set, on the TSC */ + enum class response_type + { + INTEGER, + STRING + }; + + //snmp response values can be any asn.1 supported types. + //Integer and string values can be processed here + int64_t val_int = 0; + std::vector val_string; + response_type type; + + inline bool operator==(const snmp_response_obj& obj2) const + { + return val_int == obj2.val_int && val_string == obj2.val_string && type == obj2.type; + } +}; + +class snmp_client +{ + private: + + /*variables to store an snmp session*/ + // struct that holds information about who we're going to be talking to + // We need to declare 2 of these, one to fill info with and second which is + // a pointer returned by the library + snmp_session session; + snmp_session *ss; + + /*Structure to hold all of the information that we're going to send to the remote host*/ + snmp_pdu *pdu; + + + /*OID is going to hold the location of the information which we want to receive. It will need a size as well*/ + oid OID[MAX_OID_LEN]; + size_t OID_len = MAX_OID_LEN; + + // Values from config + /*Target device IP address*/ + std::string ip_; + /*Target device NTCIP port*/ + int port_ = 0; + /*Target community for establishing snmp communication*/ + std::string community_ = "public"; + /* net-snmp version definition: SNMP_VERSION_1:0 SNMP_VERSION_2c:1 SNMP_VERSION_2u:2 SNMP_VERSION_3:3 + https://github.com/net-snmp/net-snmp/blob/master/include/net-snmp/library/snmp.h */ + int snmp_version_ = 3; // default to 3 since previous versions not compatable currently + /*Time after which the the snmp request times out*/ + int timeout_ = 10000; + + public: + /** @brief Constructor for Traffic Signal Controller Service client. + * Uses the arguments provided to establish an snmp connection + * @param ip The ip ,as a string, for the tsc_client_service to establish an snmp communication with. + * @param port Target port as integer on the host for snmp communication. + * @param community The community id as a string. Defaults to "public" if unassigned. + * @param snmp_version The snmp_version as defined in net-snmp.Default to 0 if unassigned. + * net-snmp version definition: SNMP_VERSION_1:0 SNMP_VERSION_2c:1 SNMP_VERSION_2u:2 SNMP_VERSION_3:3" + * @param timeout The time in microseconds after which an snmp session request expires. Defaults to 100 if unassigned + * **/ + snmp_client(const std::string& ip, const int& port, const std::string& community, const std::string &snmp_user, const std::string &securityLevel, const std::string &authPassPhrase, int snmp_version = 0, int timeout = 100); + + /* Disable default copy constructor*/ + snmp_client() = delete; + + + /** @brief Returns true or false depending on whether the request could be processed for given input OID at the Traffic Signal Controller. + * @param input_oid The OID to request information for. + * @param request_type The request type for which the error is being logged. Accepted values are "GET" and "SET" only. + * @param value_int The integer value for the object returned by reference. For "SET" it is the value to be set. + * For "GET", it is the value returned for the returned object by reference. + * This is an optional argument, if not provided, defaults to 0. + * @param value_str String value for the object, returned by reference. Optional argument, if not provided the value is set as an empty string + * @return Integer value at the oid, returns false if value cannot be set/requested or oid doesn't have an integer value to return.*/ + + virtual bool process_snmp_request(const std::string& input_oid, const request_type& request_type, snmp_response_obj& val); + /** @brief Finds error type from status and logs an error. + * @param status The integer value corresponding to net-snmp defined errors. macros considered are STAT_SUCCESS(0) and STAT_TIMEOUT(2) + * @param request_type The request type for which the error is being logged (GET/SET). + * @param response The snmp_pdu struct */ + + std::string SNMPGet(const std::string &oid); // Placeholder until ERVCloudForwarding updated + + virtual int get_port() const; // Returns the current port (should always be 161 or 162) + + void log_error(const int& status, const request_type& request_type, snmp_pdu *response) const; + + /** @brief Destructor for client. Closes the snmp session**/ + virtual ~snmp_client(); + +}; + +} // namespace \ No newline at end of file diff --git a/src/tmx/TmxUtils/src/SNMPClientException.cpp b/src/tmx/TmxUtils/src/SNMPClientException.cpp new file mode 100644 index 000000000..67f82fabe --- /dev/null +++ b/src/tmx/TmxUtils/src/SNMPClientException.cpp @@ -0,0 +1,8 @@ +#include "SNMPClientException.h" + +namespace tmx::utils { + + snmp_client_exception::snmp_client_exception(const std::string &msg): std::runtime_error(msg){}; + + snmp_client_exception::~snmp_client_exception() = default; +} \ No newline at end of file diff --git a/src/tmx/TmxUtils/src/SNMPClientException.h b/src/tmx/TmxUtils/src/SNMPClientException.h new file mode 100644 index 000000000..76020a5b1 --- /dev/null +++ b/src/tmx/TmxUtils/src/SNMPClientException.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +namespace tmx::utils { + /** + * @brief Runtime error related to SNMP client used to communicate with Traffic Signal Controller (NTCIP). + * + * @author Paul Bourelly + */ + class snmp_client_exception : public std::runtime_error{ + public: + /** + * @brief Destructor. + */ + ~snmp_client_exception() override; + /** + * @brief Constructor. + * @param msg String exception message. + */ + explicit snmp_client_exception(const std::string &msg ); + }; +} \ No newline at end of file diff --git a/src/v2i-hub/RSUHealthMonitorPlugin/CMakeLists.txt b/src/v2i-hub/RSUHealthMonitorPlugin/CMakeLists.txt index 7146a51a6..52fc01004 100755 --- a/src/v2i-hub/RSUHealthMonitorPlugin/CMakeLists.txt +++ b/src/v2i-hub/RSUHealthMonitorPlugin/CMakeLists.txt @@ -10,4 +10,4 @@ find_library(libasn1c .) BuildTmxPlugin() TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME} PUBLIC ${NETSNMP_INCLUDE_DIRS}) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} PUBLIC tmxutils ${NETSNMPAGENT} ${NETSNMPMIBS} ${NETSNMP} ${NETSNMP_LIBRARIES}) \ No newline at end of file +TARGET_LINK_LIBRARIES(${PROJECT_NAME} PUBLIC tmxutils ${NETSNMPAGENT} ${NETSNMPMIBS} ${NETSNMP} ${NETSNMP_LIBRARIES} jsoncpp) \ No newline at end of file diff --git a/src/v2i-hub/RSUHealthMonitorPlugin/manifest.json b/src/v2i-hub/RSUHealthMonitorPlugin/manifest.json index da6d33044..d198d8032 100755 --- a/src/v2i-hub/RSUHealthMonitorPlugin/manifest.json +++ b/src/v2i-hub/RSUHealthMonitorPlugin/manifest.json @@ -39,7 +39,7 @@ }, { "key":"RSUOIDConfigMap", - "default":"{\"RSUOIDConfig\":[{\"RsuField\":\"rsuGpsOutpuString\",\"OID\":\"1.0.15628.4.1.8.5.0\"},{\"RsuField\":\"rsuID\",\"OID\":\"1.0.15628.4.1.8.5.0\"},{\"RsuField\":\"rsuMibVersion\",\"OID\":\"1.0.15628.4.1.8.5.0\"},{\"RsuField\":\"rsuFirmwareVersion\",\"OID\":\"1.0.15628.4.1.8.5.0\"},{\"RsuField\":\"rsuManufacturer\",\"OID\":\"1.0.15628.4.1.8.5.0\"},{\"RsuField\":\"rsuIFMIndex\",\"OID\":\"1.0.15628.4.1.8.5.0\"},{\"RsuField\":\"rsuIFMPsid\",\"OID\":\"1.0.15628.4.1.8.5.0\"},{\"RsuField\":\"rsuIFMDsrcMsgId\",\"OID\":\"1.0.15628.4.1.8.5.0\"},{\"RsuField\":\"rsuIFMTxMode\",\"OID\":\"1.0.15628.4.1.8.5.0\"},{\"RsuField\":\"rsuIFMTxChannel\",\"OID\":\"1.0.15628.4.1.8.5.0\"},{\"RsuField\":\"rsuIFMEnable\",\"OID\":\"1.0.15628.4.1.8.5.0\"},{\"RsuField\":\"rsuIFMStatus\",\"OID\":\"1.0.15628.4.1.8.5.0\"},{\"RsuField\":\"rsuMode\",\"OID\":\"1.0.15628.4.1.8.5.0\"}]}", + "default":"{\"RSUOIDConfig\":[{\"RsuField\":\"rsuGpsOutpuString\",\"OID\":\"iso.3.6.1.2.1.1.9.1.3.3\"},{\"RsuField\":\"rsuID\",\"OID\":\"iso.3.6.1.2.1.1.7.0\"},{\"RsuField\":\"rsuMibVersion\",\"OID\":\"iso.3.6.1.2.1.1.7.0\"},{\"RsuField\":\"rsuFirmwareVersion\",\"OID\":\"iso.3.6.1.2.1.1.7.0\"},{\"RsuField\":\"rsuManufacturer\",\"OID\":\"iso.3.6.1.2.1.1.7.0\"},{\"RsuField\":\"rsuIFMIndex\",\"OID\":\"iso.3.6.1.2.1.1.7.0\"},{\"RsuField\":\"rsuIFMPsid\",\"OID\":\"iso.3.6.1.2.1.1.7.0\"},{\"RsuField\":\"rsuIFMDsrcMsgId\",\"OID\":\"iso.3.6.1.2.1.1.7.0\"},{\"RsuField\":\"rsuIFMTxMode\",\"OID\":\"iso.3.6.1.2.1.1.7.0\"},{\"RsuField\":\"rsuIFMTxChannel\",\"OID\":\"iso.3.6.1.2.1.1.7.0\"},{\"RsuField\":\"rsuIFMEnable\",\"OID\":\"iso.3.6.1.2.1.1.7.0\"},{\"RsuField\":\"rsuIFMStatus\",\"OID\":\"iso.3.6.1.2.1.1.7.0\"},{\"RsuField\":\"rsuMode\",\"OID\":\"iso.3.6.1.2.1.1.7.0\"}]}", "description":"OID (Object Identifier) uniquely identify managed objects in a MIB database." } ] diff --git a/src/v2i-hub/RSUHealthMonitorPlugin/src/RSUHealthMonitorPlugin.cpp b/src/v2i-hub/RSUHealthMonitorPlugin/src/RSUHealthMonitorPlugin.cpp index 87746a732..cf86db8c5 100755 --- a/src/v2i-hub/RSUHealthMonitorPlugin/src/RSUHealthMonitorPlugin.cpp +++ b/src/v2i-hub/RSUHealthMonitorPlugin/src/RSUHealthMonitorPlugin.cpp @@ -9,7 +9,6 @@ namespace RSUHealthMonitor RSUHealthMonitorPlugin::RSUHealthMonitorPlugin(std::string name) : PluginClient(name) { UpdateConfigSettings(); - // Send SNMP call to RSU status at configurable interval. std::thread rsuStatus_t(&RSUHealthMonitorPlugin::PeriodicRSUStatusReq, this); rsuStatus_t.detach(); @@ -25,17 +24,31 @@ namespace RSUHealthMonitor GetConfigValue("SNMPPort", _snmpPort); GetConfigValue("AuthPassPhrase", _authPassPhrase); GetConfigValue("SecurityUser", _securityUser); + + // Update the OID to RSU field mapping string rsuOIDMapJsonStr; GetConfigValue("RSUOIDConfigMap", rsuOIDMapJsonStr); UpdateRSUOIDConfig(rsuOIDMapJsonStr); + + // Create SNMP client and use SNMP V3 protocol + try + { + _snmpClientPtr = std::make_shared(_rsuIp, _snmpPort, "", _securityUser, "authNoPriv", _authPassPhrase, 3); + PLOG(logINFO) << "Updated SNMP client call: RSU IP: " << _rsuIp << ", RSU port: " << _snmpPort << ", User: " << _securityUser << ", auth pass phrase: " << _authPassPhrase << ", security level: " + << "authNoPriv"; + } + catch (std::exception &ex) + { + PLOG(logERROR) << "Cannot create SNMP client due to an error. The error message is: " << ex.what(); + } } - bool RSUHealthMonitorPlugin::UpdateRSUOIDConfig(string &json_str) + void RSUHealthMonitorPlugin::UpdateRSUOIDConfig(string &json_str) { if (json_str.length() == 0) { - return false; + PLOG(logERROR) << "Error updating RSU OID config due to JSON is empty."; } try { @@ -58,9 +71,7 @@ namespace RSUHealthMonitor catch (const std::exception &e) { PLOG(logERROR) << "Error updating RSU OID config" << e.what(); - return false; } - return true; } void RSUHealthMonitorPlugin::OnConfigChanged(const char *key, const char *value) @@ -74,6 +85,35 @@ namespace RSUHealthMonitor while (true) { PLOG(logERROR) << "RSU status update call at every " << _interval; + + for_each(_rsuOIDConfigMap.begin(), _rsuOIDConfigMap.end(), [this](RSUOIDConfig &config) + { + try + { + Json::Value rsuStatuJson; + PLOG(logINFO) << "SNMP RSU status call for field:"<< config.field << ", OID: " << config.oid << " RSU IP: " << _rsuIp << ", RSU port: " << _snmpPort << ", User: " << _securityUser << ", auth pass phrase: " << _authPassPhrase; + snmp_response_obj responseVal; + if(_snmpClientPtr != nullptr) + { + _snmpClientPtr->process_snmp_request(config.oid, request_type::GET, responseVal); + if(responseVal.type == snmp_response_obj::response_type::INTEGER) + { + rsuStatuJson[config.field] = responseVal.val_int; + } + else if(responseVal.type == snmp_response_obj::response_type::STRING) + { + string response_str(responseVal.val_string.begin(), responseVal.val_string.end()); + rsuStatuJson[config.field] = response_str; + } + Json::FastWriter fasterWirter; + string json_str = fasterWirter.write(rsuStatuJson); + PLOG(logINFO) << "SNMP Response: "<< json_str; + } + } + catch (std::exception &ex) + { + PLOG(logERROR) << "SNMP call failure due to: " << ex.what(); + } }); this_thread::sleep_for(chrono::seconds(_interval)); } } diff --git a/src/v2i-hub/RSUHealthMonitorPlugin/src/RSUHealthMonitorPlugin.h b/src/v2i-hub/RSUHealthMonitorPlugin/src/RSUHealthMonitorPlugin.h index 01388399b..cba7d517b 100755 --- a/src/v2i-hub/RSUHealthMonitorPlugin/src/RSUHealthMonitorPlugin.h +++ b/src/v2i-hub/RSUHealthMonitorPlugin/src/RSUHealthMonitorPlugin.h @@ -7,6 +7,8 @@ #include #include #include +#include "SNMPClient.h" +#include using namespace tmx::utils; using namespace std; @@ -31,12 +33,12 @@ namespace RSUHealthMonitor string _authPassPhrase; string _securityUser; vector _rsuOIDConfigMap; + std::shared_ptr _snmpClientPtr; /** * @brief Update RSU OID configuration map with input JSON string. * @param JSON string with RSU OID configuration. - * @return boolean indicator whether the RSU OID configuration map is updated successfully or not. */ - bool UpdateRSUOIDConfig(string &json_str); + void UpdateRSUOIDConfig(string &json_str); void PeriodicRSUStatusReq(); public: