From 3d71e5185fa9c93bde7363a668aecf96240ae2e9 Mon Sep 17 00:00:00 2001 From: Eduardo Ramos Testillano Date: Sun, 24 May 2015 19:33:10 +0200 Subject: [PATCH] New ApplicationMessageOamModule in diameter::comm, to dynamically manage application message counters --- example/diameter/launcher/Launcher.cpp | 176 ++++++++++-------- .../diameter/launcher/MyDiameterEntity.cpp | 1 + example/diameter/launcher/MyLocalServer.cpp | 4 +- include/anna/core/define.autoenum.hpp | 5 + include/anna/core/oam/Module.hpp | 21 ++- .../ApplicationMessageOamModule.hpp | 162 ++++++++++++++++ include/anna/diameter.comm/ClientSession.hpp | 2 +- include/anna/diameter.comm/Message.hpp | 1 + include/anna/diameter.comm/OamModule.hpp | 5 +- include/anna/diameter.comm/ServerSession.hpp | 2 +- include/anna/diameter/codec/OamModule.hpp | 5 +- .../ApplicationMessageOamModule.cpp | 117 ++++++++++++ source/diameter.comm/ClientSession.cpp | 31 ++- source/diameter.comm/Message.cpp | 5 + source/diameter.comm/ServerSession.cpp | 32 +++- 15 files changed, 473 insertions(+), 96 deletions(-) create mode 100644 include/anna/diameter.comm/ApplicationMessageOamModule.hpp create mode 100644 source/diameter.comm/ApplicationMessageOamModule.cpp diff --git a/example/diameter/launcher/Launcher.cpp b/example/diameter/launcher/Launcher.cpp index e4ea4ca..edb1de0 100644 --- a/example/diameter/launcher/Launcher.cpp +++ b/example/diameter/launcher/Launcher.cpp @@ -14,6 +14,7 @@ #include #include #include +#include // Process #include "Launcher.hpp" @@ -359,13 +360,85 @@ throw(anna::RuntimeException) { a_start_time.setNow(); // Statistics: anna::statistics::Engine::instantiate().enable(); + + // Checking command line parameters + if(cl.exists("sessionBasedModelsClientSocketSelection")) { + std::string type = cl.getValue("sessionBasedModelsClientSocketSelection"); + + if((type != "SessionIdHighPart") && (type != "SessionIdOptionalPart") && (type != "RoundRobin")) { + throw anna::RuntimeException("Commandline option '-sessionBasedModelsClientSocketSelection' only accepts 'SessionIdHighPart'/'SessionIdOptionalPart'/'RoundRobin' as parameter values", ANNA_FILE_LOCATION); + } + } + + // Tracing: + if(cl.exists("trace")) + anna::Logger::setLevel(anna::Logger::asLevel(cl.getValue("trace"))); + + LOGINFORMATION( + // Help on startup traces: + anna::Logger::information(help(), ANNA_FILE_LOCATION); + // Test messages dtd: + std::string msg = "\n ------------- TESTMESSAGES DTD -------------\n"; + msg += anna::diameter::codec::MessageDTD; + anna::Logger::information(msg, ANNA_FILE_LOCATION); + ); + + // HTTP Server: + if(cl.exists("httpServer")) { + anna::comm::Network& network = anna::comm::Network::instantiate(); + std::string address; + int port; + anna::functions::getAddressAndPortFromSocketLiteral(cl.getValue("httpServer"), address, port); + //const anna::comm::Device* device = network.find(Device::asAddress(address)); // here provide IP + const anna::comm::Device* device = *((network.resolve(address)->device_begin())); // trick to solve + a_httpServerSocket = new anna::comm::ServerSocket(anna::comm::INetAddress(device, port), cl.exists("httpServerShared") /* shared bind */, &anna::http::Transport::getFactory()); + } + + // Stack: + anna::diameter::codec::Engine *codecEngine = new anna::diameter::codec::Engine(); + anna::diameter::stack::Engine &stackEngine = anna::diameter::stack::Engine::instantiate(); + anna::diameter::stack::Dictionary * d = stackEngine.createDictionary(0 /* stack id; its value don't mind, is not used (ADL is monostack) */); + // Analyze comma-separated list: + anna::Tokenizer lst; + std::string dictionaryParameter = cl.getValue("dictionary"); + lst.apply(dictionaryParameter, ","); + + if(lst.size() >= 1) { // always true (at least one, because -dictionary is mandatory) + anna::Tokenizer::const_iterator tok_min(lst.begin()); + anna::Tokenizer::const_iterator tok_max(lst.end()); + anna::Tokenizer::const_iterator tok_iter; + std::string pathFile; + d->allowUpdates(); + + for(tok_iter = tok_min; tok_iter != tok_max; tok_iter++) { + pathFile = anna::Tokenizer::data(tok_iter); + d->load(pathFile); + } + } + + codecEngine->setDictionary(d); + LOGDEBUG(anna::Logger::debug(codecEngine->asString(), ANNA_FILE_LOCATION)); + + if(lst.size() > 1) { + std::string all_in_one = "./dictionary-all-in-one.xml"; + std::ofstream out(all_in_one.c_str(), std::ifstream::out); + std::string buffer = d->asXMLString(); + out.write(buffer.c_str(), buffer.size()); + out.close(); + std::cout << "Written accumulated '" << all_in_one << "' (provide it next time to be more comfortable)." << std::endl; + } + /////////////////////////////// // Diameter library COUNTERS // /////////////////////////////// anna::diameter::comm::OamModule & oamDiameterComm = anna::diameter::comm::OamModule::instantiate(); oamDiameterComm.initializeCounterScope(1); // 1000 - 1999 + oamDiameterComm.enableCounters(); + oamDiameterComm.enableAlarms(); anna::diameter::codec::OamModule & oamDiameterCodec = anna::diameter::codec::OamModule::instantiate(); oamDiameterCodec.initializeCounterScope(2); // 2000 - 2999 + oamDiameterCodec.enableCounters(); + oamDiameterCodec.enableAlarms(); ///////////////// // COMM MODULE // ///////////////// @@ -463,6 +536,18 @@ throw(anna::RuntimeException) { oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::LevelValidation__FailedRuleForCardinalityMoreThanNeeded, "", 17 /*2017*/); oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::LevelValidation__FailedGenericAvpRuleForCardinalityFoundDisregardedItem, "", 18 /*2018*/); oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::LevelValidation__FoundDisregardedItemsAndGenericAVPWasNotSpecified, "", 19 /*2019*/); + /////////////////////////////////////////// + // APPLICATION MESSAGE OAM MODULE SCOPES // + /////////////////////////////////////////// + // We will register a scope per stack id registered. The counters will be dynamically registered at count method. + anna::diameter::comm::ApplicationMessageOamModule & appMsgOamModule = anna::diameter::comm::ApplicationMessageOamModule::instantiate(); + int scope_id = 3; + for (anna::diameter::stack::Engine::const_stack_iterator it = stackEngine.stack_begin(); it != stackEngine.stack_end(); it++) { + appMsgOamModule.createStackCounterScope(scope_id, it->first); + scope_id++; + } + appMsgOamModule.enableCounters(); // this special module is disabled by default (the only) + ///////////////////////////////// // Counter recorder associated // @@ -470,77 +555,10 @@ throw(anna::RuntimeException) { if(a_counterRecorderClock) { oamDiameterComm.setCounterRecorder(a_counterRecorder); oamDiameterCodec.setCounterRecorder(a_counterRecorder); + appMsgOamModule.setCounterRecorder(a_counterRecorder); a_timeEngine->activate(a_counterRecorderClock); // start clock } - // Checking command line parameters - if(cl.exists("sessionBasedModelsClientSocketSelection")) { - std::string type = cl.getValue("sessionBasedModelsClientSocketSelection"); - - if((type != "SessionIdHighPart") && (type != "SessionIdOptionalPart") && (type != "RoundRobin")) { - throw anna::RuntimeException("Commandline option '-sessionBasedModelsClientSocketSelection' only accepts 'SessionIdHighPart'/'SessionIdOptionalPart'/'RoundRobin' as parameter values", ANNA_FILE_LOCATION); - } - } - - // Tracing: - if(cl.exists("trace")) - anna::Logger::setLevel(anna::Logger::asLevel(cl.getValue("trace"))); - - LOGINFORMATION( - // Help on startup traces: - anna::Logger::information(help(), ANNA_FILE_LOCATION); - // Test messages dtd: - std::string msg = "\n ------------- TESTMESSAGES DTD -------------\n"; - msg += anna::diameter::codec::MessageDTD; - anna::Logger::information(msg, ANNA_FILE_LOCATION); - ); - - // HTTP Server: - if(cl.exists("httpServer")) { - anna::comm::Network& network = anna::comm::Network::instantiate(); - std::string address; - int port; - anna::functions::getAddressAndPortFromSocketLiteral(cl.getValue("httpServer"), address, port); - //const anna::comm::Device* device = network.find(Device::asAddress(address)); // here provide IP - const anna::comm::Device* device = *((network.resolve(address)->device_begin())); // trick to solve - a_httpServerSocket = new anna::comm::ServerSocket(anna::comm::INetAddress(device, port), cl.exists("httpServerShared") /* shared bind */, &anna::http::Transport::getFactory()); - } - - // Stack: - anna::diameter::codec::Engine *codecEngine = new anna::diameter::codec::Engine(); - anna::diameter::stack::Engine &stackEngine = anna::diameter::stack::Engine::instantiate(); - anna::diameter::stack::Dictionary * d = stackEngine.createDictionary(0 /* stack id; its value don't mind, is not used (ADL is monostack) */); - // Analyze comma-separated list: - anna::Tokenizer lst; - std::string dictionaryParameter = cl.getValue("dictionary"); - lst.apply(dictionaryParameter, ","); - - if(lst.size() >= 1) { // always true (at least one, because -dictionary is mandatory) - anna::Tokenizer::const_iterator tok_min(lst.begin()); - anna::Tokenizer::const_iterator tok_max(lst.end()); - anna::Tokenizer::const_iterator tok_iter; - std::string pathFile; - d->allowUpdates(); - - for(tok_iter = tok_min; tok_iter != tok_max; tok_iter++) { - pathFile = anna::Tokenizer::data(tok_iter); - d->load(pathFile); - } - } - - codecEngine->setDictionary(d); - LOGDEBUG(anna::Logger::debug(codecEngine->asString(), ANNA_FILE_LOCATION)); - - if(lst.size() > 1) { - std::string all_in_one = "./dictionary-all-in-one.xml"; - std::ofstream out(all_in_one.c_str(), std::ifstream::out); - std::string buffer = d->asXMLString(); - out.write(buffer.c_str(), buffer.size()); - out.close(); - std::cout << "Written accumulated '" << all_in_one << "' (provide it next time to be more comfortable)." << std::endl; - } - - // Integration (validation 'Complete' for receiving messages) and debugging (validation also before encoding: 'Always'). // If missing 'integrationAndDebugging', default behaviour at engine is: mode 'AfterDecoding', depth 'FirstError': @@ -911,9 +929,9 @@ std::string Launcher::gotoBurst(int order) throw() { } void Launcher::resetCounters() throw() { - // Diameter::comm module: - anna::diameter::comm::OamModule & oamDiameterComm = anna::diameter::comm::OamModule::instantiate(); - oamDiameterComm.resetCounters(); + anna::diameter::comm::OamModule::instantiate().resetCounters(); + anna::diameter::comm::ApplicationMessageOamModule::instantiate().resetCounters(); + anna::diameter::codec::OamModule::instantiate().resetCounters(); } void Launcher::signalUSR2() throw(anna::RuntimeException) { @@ -1041,9 +1059,13 @@ std::string Launcher::help() const throw() { result += "\n"; result += "\ndiameterServerSessions| Updates the maximum number of accepted connections to diameter"; result += "\n server socket."; + result += "\ncontext|[target file] Application context could also be written by mean this operation,"; + result += "\n and not only through SIGUSR1. If optional path file is missing,"; + result += "\n default '/var/tmp/anna.context.' will be used."; result += "\ncollect Reset statistics and counters to start a new test stage of"; - result += "\n performance measurement. Context data is written at"; - result += "\n '/var/tmp/anna.context.' by mean 'kill -10 '."; + result += "\n performance measurement. Context data can be written at"; + result += "\n '/var/tmp/anna.context.' by mean 'kill -10 '"; + result += "\n or sending operation 'context|[target file]'."; result += "\nforceCountersRecord Forces dump to file the current counters of the process."; result += "\n"; result += "\n|[
:]|[socket id]"; @@ -1272,6 +1294,13 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons if(numParams == 2) { tok_iter++; param2 = Tokenizer::data(tok_iter); } // Operations: + if(opType == "context") { + std::string contextFile = ((numParams == 1) ? param1 : anna::functions::asString("/var/tmp/anna.context.%05d", getPid())); + writeContext(contextFile); + response_content = anna::functions::asString("Context dumped on file '%s'\n", contextFile.c_str()); + return; + } + if(opType == "code") { codecMsg.loadXML(param1); std::string hexString = anna::functions::asHexString(codecMsg.code()); @@ -1698,6 +1727,7 @@ throw() { (anna::functions::component (ANNA_FILE_LOCATION))->asXML(result); // OAM: anna::diameter::comm::OamModule::instantiate().asXML(result); + anna::diameter::comm::ApplicationMessageOamModule::instantiate().asXML(result); anna::diameter::codec::OamModule::instantiate().asXML(result); // Statistics: anna::statistics::Engine::instantiate().asXML(result); diff --git a/example/diameter/launcher/MyDiameterEntity.cpp b/example/diameter/launcher/MyDiameterEntity.cpp index 0535160..f6fce7b 100644 --- a/example/diameter/launcher/MyDiameterEntity.cpp +++ b/example/diameter/launcher/MyDiameterEntity.cpp @@ -145,6 +145,7 @@ throw(anna::RuntimeException) { msg += anna::diameter::functions::commandIdAsPairString(request_cid); anna::Logger::debug(msg, ANNA_FILE_LOCATION); ); + // Write reception if(request_cid != anna::diameter::helpers::base::COMMANDID__Capabilities_Exchange_Request) { // don't trace CEA if(my_app.logEnabled()) { diff --git a/example/diameter/launcher/MyLocalServer.cpp b/example/diameter/launcher/MyLocalServer.cpp index 5e3ca1f..7db0d87 100644 --- a/example/diameter/launcher/MyLocalServer.cpp +++ b/example/diameter/launcher/MyLocalServer.cpp @@ -105,7 +105,6 @@ throw(anna::RuntimeException) { if(my_app.logEnabled()) my_app.writeLogFile(*answer_message, "sent2c", serverSession->asString()); } catch(anna::RuntimeException &ex) { ex.trace(); - if(my_app.logEnabled()) my_app.writeLogFile(*answer_message, "send2cError", serverSession->asString()); } @@ -180,7 +179,7 @@ throw(anna::RuntimeException) { anna::diameter::comm::ClientSession *usedClientSession = my_app.getMyDiameterEngine()->findClientSession(request->getRequestClientSessionKey()); std::string detail; - if(my_app.logEnabled()) detail = usedClientSession ? usedClientSession->asString() : ""; // esto no deberia ocurrir + if(my_app.logEnabled()) detail = usedClientSession ? usedClientSession->asString() : ""; // this should not happen try { anna::diameter::comm::Message *msg = my_app.createCommMessage(); @@ -200,7 +199,6 @@ throw(anna::RuntimeException) { if(my_app.logEnabled()) my_app.writeLogFile(*message, "fwd2e", detail); // forwarded } catch(anna::RuntimeException &ex) { ex.trace(); - if(my_app.logEnabled()) my_app.writeLogFile(*message, "fwd2eError", detail); // forwarded } } diff --git a/include/anna/core/define.autoenum.hpp b/include/anna/core/define.autoenum.hpp index 748dbce..9378110 100644 --- a/include/anna/core/define.autoenum.hpp +++ b/include/anna/core/define.autoenum.hpp @@ -47,6 +47,11 @@ */ #define anna_declare_enum(name) \ static const char* literal []; \ + static int calculateSize () throw () { \ + int ii = 0; \ + while (literal [ii] != NULL) ii ++; \ + return ii; \ + } \ static _v asEnum (const char* str) throw () { \ for (int ii = 0; literal [ii] != NULL; ii ++) { \ if (strcasecmp (str, literal [ii]) == 0) \ diff --git a/include/anna/core/oam/Module.hpp b/include/anna/core/oam/Module.hpp index 10e051f..39bc31c 100644 --- a/include/anna/core/oam/Module.hpp +++ b/include/anna/core/oam/Module.hpp @@ -138,8 +138,8 @@ class Module { Handler *a_handler; // Handler reference std::string a_className; // module description - bool a_counters_enabled; // Enable/Disable registered counters over this module (default is 'true') - bool a_alarms_enabled; // Enable/Disable registered alarms over this module (default is 'true') + bool a_counters_enabled; // Enable/Disable registered counters over this module (default is 'false') + bool a_alarms_enabled; // Enable/Disable registered alarms over this module (default is 'false') // dynamic modifications over alarm text bool a_alarms_preffix_enabled; // Show own module alarm preffix @@ -202,10 +202,9 @@ class Module { alarm_iterator alarm_end() throw() { return a_alarms.end(); } void getAlarmPreffixSuffixAndZoneSeparator(std::string & preffix, std::string & suffix, char & zS) const throw(); - public: - static const int MaxScope = 100; /**< Numero maximo de ambitos */ + static const int MaxScope = 1000; /**< Numero maximo de ambitos */ /** Constructor @@ -213,10 +212,10 @@ public: */ Module(const std::string &className) : a_className(className), a_handler(&a_defaultHandler), - a_counters_enabled(true), + a_counters_enabled(false), a_counterRecorder(NULL), a_counterRecording(false), - a_alarms_enabled(true), + a_alarms_enabled(false), a_alarms_preffix_enabled(true), a_alarms_suffix_enabled(true) {;} @@ -250,6 +249,16 @@ public: */ void disableAlarms(void) throw(); + /** + Getter for counters enabled + */ + bool countersEnabled() const throw() { return a_counters_enabled; } + + /** + Getter for alarms enabled + */ + bool alarmsEnabled() const throw() { return a_alarms_enabled; } + /** * Show own module alarm preffix (enabled by default at constructor). * Usually managed at PROCCESS implementation diff --git a/include/anna/diameter.comm/ApplicationMessageOamModule.hpp b/include/anna/diameter.comm/ApplicationMessageOamModule.hpp new file mode 100644 index 0000000..c9c5b0d --- /dev/null +++ b/include/anna/diameter.comm/ApplicationMessageOamModule.hpp @@ -0,0 +1,162 @@ +// ANNA - Anna is Not Nothingness Anymore // +// // +// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo // +// // +// See project site at http://redmine.teslayout.com/projects/anna-suite // +// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // + + +#ifndef anna_diameter_comm_ApplicationMessageOamModule_hpp +#define anna_diameter_comm_ApplicationMessageOamModule_hpp + + +// Project +#include +#include +#include +#include + +// Standard +#include +#include + +namespace anna { + +namespace diameter { + +namespace comm { + + +/** + Special OAM module which tracks a replica for a set of counter types for each different application message managed by the + communication layer in a specific stack id. For example, if one process is managing CCR/A, RAR/A for Gx and AAR/A, RAR/A for Rx, + then two counter scopes should be registered (one for Gx, another for Rx). Each scope will store counters sets for each diameter + message. Having N counters within each scope (for example N=14), the total capacity is N/(number of counter types) different + message codes: + +
+    Scope for Gx:
+
+      Credit-Control-Request_SentOK_AsClient
+      Credit-Control-Request_SentNOK_AsClient
+      Credit-Control-Answer_SentOK_AsClient
+      Credit-Control-Answer_SentNOK_AsClient
+      Credit-Control-Request_Received_AsClient
+      Credit-Control-Answer_Received_AsClient
+      Credit-Control-Answer_UnknownReceived_AsClient
+      Credit-Control-Request_SentOK_AsServer
+      Credit-Control-Request_SentNOK_AsServer
+      Credit-Control-Answer_SentOK_AsServer
+      Credit-Control-Answer_SentNOK_AsServer
+      Credit-Control-Request_Received_AsServer
+      Credit-Control-Answer_Received_AsServer
+      Credit-Control-Answer_UnknownReceived_AsServer
+      Re-Auth-Request_SentOK_AsClient
+      Re-Auth-Request_SentNOK_AsClient
+      Re-Auth-Answer_SentOK_AsClient
+      Re-Auth-Answer_SentNOK_AsClient
+      Re-Auth-Request_Received_AsClient
+      Re-Auth-Answer_Received_AsClient
+      Re-Auth-Answer_UnknownReceived_AsClient
+      Re-Auth-Request_SentOK_AsServer
+      Re-Auth-Request_SentNOK_AsServer
+      Re-Auth-Answer_SentOK_AsServer
+      Re-Auth-Answer_SentNOK_AsServer
+      Re-Auth-Request_Received_AsServer
+      Re-Auth-Answer_Received_AsServer
+      Re-Auth-Answer_UnknownReceived_AsServer
+   
+    Scope for Rx:
+
+      AA-Request_SentOK_AsClient
+      AA-Request_SentNOK_AsClient
+      AA-Answer_SentOK_AsClient
+      AA-Answer_SentNOK_AsClient
+      AA-Request_Received_AsClient
+      AA-Answer_Received_AsClient
+      AA-Answer_UnknownReceived_AsClient
+      AA-Request_SentOK_AsServer
+      AA-Request_SentNOK_AsServer
+      AA-Answer_SentOK_AsServer
+      AA-Answer_SentNOK_AsServer
+      AA-Request_Received_AsServer
+      AA-Answer_Received_AsServer
+      AA-Answer_UnknownReceived_AsServer
+      Re-Auth-Request_SentOK_AsClient
+      Re-Auth-Request_SentNOK_AsClient
+      Re-Auth-Answer_SentOK_AsClient
+      Re-Auth-Answer_SentNOK_AsClient
+      Re-Auth-Request_Received_AsClient
+      Re-Auth-Answer_Received_AsClient
+      Re-Auth-Answer_UnknownReceived_AsClient
+      Re-Auth-Request_SentOK_AsServer
+      Re-Auth-Request_SentNOK_AsServer
+      Re-Auth-Answer_SentOK_AsServer
+      Re-Auth-Answer_SentNOK_AsServer
+      Re-Auth-Request_Received_AsServer
+      Re-Auth-Answer_Received_AsServer
+      Re-Auth-Answer_UnknownReceived_AsServer
+  
+*/ +class ApplicationMessageOamModule : public anna::oam::Module, public anna::Singleton { + + std::map a_messageMap; + std::map a_stackMap; + + int a_counter_types; + + anna::Mutex a_mutex; // counter scope switch + +public: + + struct Counter { + enum _v + { + None = -1, + + Request_SentOK_AsClient, + Request_SentNOK_AsClient, + Answer_SentOK_AsClient, + Answer_SentNOK_AsClient, + Request_Received_AsClient, + Answer_Received_AsClient, + Answer_UnknownReceived_AsClient, + + Request_SentOK_AsServer, + Request_SentNOK_AsServer, + Answer_SentOK_AsServer, + Answer_SentNOK_AsServer, + Request_Received_AsServer, + Answer_Received_AsServer, + Answer_UnknownReceived_AsServer + }; + + anna_declare_enum(Counter); + }; + + /* virtual */std::string getDefaultInternalCounterDescription(const int & counterType) const throw() { return Counter::asCString((Counter::_v)counterType); } + + // map stack id with a scope id + void createStackCounterScope(int /* scope id */, unsigned int /* stack id */) throw(anna::RuntimeException); + + // translate message code into offset and invoke parent class count method. The message applicationId will be used as stack id + void count (int messageCode, unsigned int stackId, const int & type, const int & amount = 1) throw(anna::RuntimeException); + + // Number of different counter types for each message + int getCounterTypes() const throw() { return a_counter_types; } + +private: + + // private constructor + ApplicationMessageOamModule() : anna::oam::Module("Application Message Comm OAM Events") { a_counter_types = Counter::calculateSize(); } + + + friend class anna::Singleton ; +}; + +} +} +} + +#endif + diff --git a/include/anna/diameter.comm/ClientSession.hpp b/include/anna/diameter.comm/ClientSession.hpp index b343f53..93490cb 100644 --- a/include/anna/diameter.comm/ClientSession.hpp +++ b/include/anna/diameter.comm/ClientSession.hpp @@ -222,7 +222,7 @@ private: // Activity: /* virtual */void updateIncomingActivityTime() throw(); /* virtual */void updateOutgoingActivityTime() throw(); - void countSendings(const diameter::CommandId & cid, bool ok) throw(); + void countSendings(const diameter::CommandId & cid, unsigned int aid, bool ok) throw(); // Handlers: /** diff --git a/include/anna/diameter.comm/Message.hpp b/include/anna/diameter.comm/Message.hpp index fe9da01..b5cb459 100644 --- a/include/anna/diameter.comm/Message.hpp +++ b/include/anna/diameter.comm/Message.hpp @@ -105,6 +105,7 @@ public: void setRequestEndToEnd(EndToEnd ete) throw() { a_requestEndToEnd = ete; } CommandId getCommandId(bool &isRequest) const throw(); CommandId getCommandId() const throw() { bool dummy; return getCommandId(dummy); } + ApplicationId getApplicationId() const throw(); bool fixRequestSequence(HopByHop hbh, EndToEnd ete) throw(); diff --git a/include/anna/diameter.comm/OamModule.hpp b/include/anna/diameter.comm/OamModule.hpp index 346c12f..6566180 100644 --- a/include/anna/diameter.comm/OamModule.hpp +++ b/include/anna/diameter.comm/OamModule.hpp @@ -10,13 +10,12 @@ #define anna_diameter_comm_OamModule_hpp +// Project #include #include - -// HTE #include -// STL +// Standard #include diff --git a/include/anna/diameter.comm/ServerSession.hpp b/include/anna/diameter.comm/ServerSession.hpp index 23d3ba6..5581a4b 100644 --- a/include/anna/diameter.comm/ServerSession.hpp +++ b/include/anna/diameter.comm/ServerSession.hpp @@ -159,7 +159,7 @@ private: // Activity: /* virtual */void updateIncomingActivityTime() throw(); /* virtual */void updateOutgoingActivityTime() throw(); - void countSendings(const diameter::CommandId & cid, bool ok) throw(); + void countSendings(const diameter::CommandId & cid, unsigned int aid, bool ok) throw(); // Handlers: /** diff --git a/include/anna/diameter/codec/OamModule.hpp b/include/anna/diameter/codec/OamModule.hpp index 15e7b9f..0ef5aa4 100644 --- a/include/anna/diameter/codec/OamModule.hpp +++ b/include/anna/diameter/codec/OamModule.hpp @@ -10,13 +10,12 @@ #define anna_diameter_codec_OamModule_hpp +// Project #include #include - -// HTE #include -// STL +// Standard #include diff --git a/source/diameter.comm/ApplicationMessageOamModule.cpp b/source/diameter.comm/ApplicationMessageOamModule.cpp new file mode 100644 index 0000000..bba049c --- /dev/null +++ b/source/diameter.comm/ApplicationMessageOamModule.cpp @@ -0,0 +1,117 @@ +// ANNA - Anna is Not Nothingness Anymore // +// // +// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo // +// // +// See project site at http://redmine.teslayout.com/projects/anna-suite // +// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE // + + +// Standard +#include + +// Project +#include +#include +#include +#include +#include + + +anna_assign_enum(anna::diameter::comm::ApplicationMessageOamModule::Counter) = { \ + "Request_SentOK_AsClient", \ + "Request_SentNOK_AsClient", \ + "Answer_SentOK_AsClient", \ + "Answer_SentNOK_AsClient", \ + "Request_Received_AsClient", \ + "Answer_Received_AsClient", \ + "Answer_UnknownReceived_AsClient", \ + + "Request_SentOK_AsServer", \ + "Request_SentNOK_AsServer", \ + "Answer_SentOK_AsServer", \ + "Answer_SentNOK_AsServer", \ + "Request_Received_AsServer", \ + "Answer_Received_AsServer", \ + "Answer_UnknownReceived_AsServer", \ + NULL /* list end indicator */ +}; + +void anna::diameter::comm::ApplicationMessageOamModule::createStackCounterScope(int scopeId, unsigned int stackId) throw(anna::RuntimeException) { + + initializeCounterScope(scopeId, anna::functions::asString("Application Message Events for stack id %lu", stackId)); + + // Better to be enabled by application in order to be more conscious of the native disabled nature of this special oam module + //if (!countersEnabled()) enableCounters(); + //enableAlarms(); not yet implemented + + a_stackMap[stackId] = scopeId; +} + +void anna::diameter::comm::ApplicationMessageOamModule::count (int messageCode, unsigned int stackId, const int & type, const int & amount) throw(anna::RuntimeException) { + + // Optimization: + // Checkings + if(!countersEnabled()) { + LOGDEBUG + ( + std::string msg = "Count operation ignored over module '"; + msg += getClassName(); + msg += "': counters are disabled"; + anna::Logger::debug(msg, ANNA_FILE_LOCATION); + ); + return; + } + + anna::Guard guard(a_mutex, "ApplicationMessageOamModule::count"); // counter scope switch + + std::map::const_iterator stackMap_it = a_stackMap.find(stackId); + + if (stackMap_it == a_stackMap.end()) { + LOGDEBUG(anna::Logger::debug(anna::functions::asString("Unregistered stack id %lu", stackId), ANNA_FILE_LOCATION)); + return; + } + + // Select counter scope + setActiveCounterScope(stackMap_it->second); + + std::map::const_iterator messageMap_it = a_messageMap.find(messageCode); + int baseOffset = messageMap_it->second; + + if (messageMap_it == a_messageMap.end()) { + int capacity = anna::oam::CounterScope::MaxCounter / getCounterTypes(); + if (a_messageMap.size() > capacity) { + LOGDEBUG(anna::Logger::debug(anna::functions::asString("No more holes to register new application message counters in the scope (up to %d message codes)", capacity), ANNA_FILE_LOCATION)); + return; + } + baseOffset = getCounterTypes() * a_messageMap.size(); // N counter types for each message code + a_messageMap[messageCode] = baseOffset; + + // Counter name: + std::string counterNamePrefix = anna::functions::asString("ApplicationMessageCode_%d", messageCode); // default + anna::diameter::stack::Engine &stackEngine = anna::diameter::stack::Engine::instantiate(); + const anna::diameter::stack::Dictionary *dictionary = stackEngine.getDictionary(stackId); + if (dictionary) { + anna::diameter::CommandId cidR(messageCode, true /* request */); + anna::diameter::CommandId cidA(messageCode, false /* answer */); + const anna::diameter::stack::Command *commandR = dictionary->getCommand(cidR); + const anna::diameter::stack::Command *commandA = dictionary->getCommand(cidA); + if (commandR && commandA) { + std::string string1 = commandR->getName(); + std::string string2 = commandA->getName(); + std::string intersection; // non-standard names will be also intersected: XXR and XXA gives XX + std::set_intersection(string1.begin(), string1.end(), string2.begin(), string2.end(), std::back_inserter(intersection)); + counterNamePrefix = intersection; + // Special case: + if (counterNamePrefix == "") counterNamePrefix = string1 + "#" + string2; + } + } + + if (counterNamePrefix[counterNamePrefix.size() - 1] != '-') counterNamePrefix += "-"; + for (int offset = 0; offset < getCounterTypes(); offset++) + registerCounter(baseOffset + offset, counterNamePrefix + getDefaultInternalCounterDescription(offset), baseOffset + offset); + } + + // Count + Module::count(baseOffset + type, amount); +} + diff --git a/source/diameter.comm/ClientSession.cpp b/source/diameter.comm/ClientSession.cpp index 91aa8cf..7974ae7 100644 --- a/source/diameter.comm/ClientSession.cpp +++ b/source/diameter.comm/ClientSession.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -153,6 +154,8 @@ const Response* ClientSession::send(const Message* message) throw(anna::RuntimeE // Command id: bool isRequest; diameter::CommandId cid = message->getCommandId(isRequest); + diameter::ApplicationId aid = message->getApplicationId(); + LOGDEBUG( std::string msg = "Sending diameter message: "; msg += anna::diameter::functions::commandIdAsPairString(cid); @@ -296,7 +299,7 @@ const Response* ClientSession::send(const Message* message) throw(anna::RuntimeE // updateOutgoingActivityTime(); // OAM - countSendings(cid, true /* send ok */); + countSendings(cid, aid, true /* send ok */); // Trace non-application messages: LOGDEBUG( @@ -314,7 +317,7 @@ const Response* ClientSession::send(const Message* message) throw(anna::RuntimeE if(fixed) message_nc->restoreSequencesAfterFix(); // restore to application sequences after fix // OAM - countSendings(cid, false /* send no ok */); + countSendings(cid, aid, false /* send no ok */); throw; } @@ -524,6 +527,9 @@ throw(anna::RuntimeException) { } try { + // application message counters + ApplicationMessageOamModule::instantiate().count(cid.first, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Request_Received_AsClient); + eventRequest(db); } catch(anna::RuntimeException& ex) { ex.trace(); @@ -624,6 +630,10 @@ throw(anna::RuntimeException) { oamModule.count(OamModule::Counter::AnswerReceivedUnknown); oamModule.count(OamModule::Counter::AnswerReceivedOnClientSessionUnknown); oamModule.activateAlarm(OamModule::Alarm::AnswerReceivedOnClientSessionUnknown); + + // application message counters + ApplicationMessageOamModule::instantiate().count(cid.first, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Answer_UnknownReceived_AsClient); + eventUnknownResponse(db); string msg(asString()); msg += anna::functions::asString(" | Response received from entity, for non registered context (HopByHop: %u)", hopByHop); @@ -669,6 +679,11 @@ throw(anna::RuntimeException) { ); diameter::codec::functions::setHopByHop((anna::DataBlock&)db, response->getRequest()->getRequestHopByHop()); diameter::codec::functions::setEndToEnd((anna::DataBlock&)db, response->getRequest()->getRequestEndToEnd()); + + // application message counters + if(cid != helpers::base::COMMANDID__Capabilities_Exchange_Answer) + ApplicationMessageOamModule::instantiate().count(cid.first, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Answer_Received_AsClient); + eventResponse(*response); } catch(anna::RuntimeException& ex) { ex.trace(); @@ -922,8 +937,10 @@ void ClientSession::updateOutgoingActivityTime(void) throw() { //------------------------------------------------------------------------------ //----------------------------------------------- ClientSession::countSendings() //------------------------------------------------------------------------------ -void ClientSession::countSendings(const diameter::CommandId & cid, bool ok)throw() { +void ClientSession::countSendings(const diameter::CommandId & cid, unsigned int aid, bool ok)throw() { OamModule &oamModule = OamModule::instantiate(); + ApplicationMessageOamModule &appMsgOamModule = ApplicationMessageOamModule::instantiate(); + bool isRequest = cid.second; if(ok) { @@ -936,6 +953,10 @@ void ClientSession::countSendings(const diameter::CommandId & cid, bool ok)throw else if(cid == helpers::base::COMMANDID__Device_Watchdog_Answer) oamModule.count(OamModule::Counter::DWASentOK); // not usual (dwr was received from server) else if(cid == helpers::base::COMMANDID__Disconnect_Peer_Request) oamModule.count(OamModule::Counter::DPRSentOK); else if(cid == helpers::base::COMMANDID__Disconnect_Peer_Answer) oamModule.count(OamModule::Counter::DPASentOK); + // Application messages: + else { + appMsgOamModule.count(cid.first, aid, isRequest ? ApplicationMessageOamModule::Counter::Request_SentOK_AsClient : ApplicationMessageOamModule::Counter::Answer_SentOK_AsClient); + } } else { // Main counters: oamModule.count(isRequest ? OamModule::Counter::RequestSentNOK : OamModule::Counter::AnswerSentNOK); @@ -946,6 +967,10 @@ void ClientSession::countSendings(const diameter::CommandId & cid, bool ok)throw else if(cid == helpers::base::COMMANDID__Device_Watchdog_Answer) oamModule.count(OamModule::Counter::DWASentNOK); // not usual (dwr was received from server) else if(cid == helpers::base::COMMANDID__Disconnect_Peer_Request) oamModule.count(OamModule::Counter::DPRSentNOK); else if(cid == helpers::base::COMMANDID__Disconnect_Peer_Answer) oamModule.count(OamModule::Counter::DPASentNOK); + // Application messages: + else { + appMsgOamModule.count(cid.first, aid, isRequest ? ApplicationMessageOamModule::Counter::Request_SentNOK_AsClient : ApplicationMessageOamModule::Counter::Answer_SentNOK_AsClient); + } } } diff --git a/source/diameter.comm/Message.cpp b/source/diameter.comm/Message.cpp index 0eef96c..88cbe91 100644 --- a/source/diameter.comm/Message.cpp +++ b/source/diameter.comm/Message.cpp @@ -143,6 +143,11 @@ anna::diameter::CommandId Message::getCommandId(bool &isRequest) const throw() { return result; } +anna::diameter::ApplicationId Message::getApplicationId() const throw() { + diameter::ApplicationId result = diameter::codec::functions::getApplicationId(getBody()); + return result; +} + HopByHop Message::getHopByHop() const throw() { return (diameter::codec::functions::getHopByHop(getBody())); } diff --git a/source/diameter.comm/ServerSession.cpp b/source/diameter.comm/ServerSession.cpp index 1be1470..3c493d0 100644 --- a/source/diameter.comm/ServerSession.cpp +++ b/source/diameter.comm/ServerSession.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -90,6 +91,8 @@ const Response* ServerSession::send(const Message* message) throw(anna::RuntimeE // Command id: bool isRequest; diameter::CommandId cid = message->getCommandId(isRequest); + diameter::ApplicationId aid = message->getApplicationId(); + LOGDEBUG( std::string msg = "Sending diameter message: "; msg += anna::diameter::functions::commandIdAsPairString(cid); @@ -208,7 +211,7 @@ const Response* ServerSession::send(const Message* message) throw(anna::RuntimeE // updateOutgoingActivityTime(); // OAM - countSendings(cid, true /* send ok */); + countSendings(cid, aid, true /* send ok */); // Trace non-application messages: LOGDEBUG( @@ -225,7 +228,7 @@ const Response* ServerSession::send(const Message* message) throw(anna::RuntimeE if(fixed) message_nc->restoreSequencesAfterFix(); // restore to application sequences after fix // OAM - countSendings(cid, false /* send no ok */); + countSendings(cid, aid, false /* send no ok */); throw; } @@ -395,6 +398,9 @@ throw(anna::RuntimeException) { } try { + // application message counters + ApplicationMessageOamModule::instantiate().count(cid.first, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Request_Received_AsServer); + eventRequest(db); } catch(anna::RuntimeException& ex) { ex.trace(); @@ -444,7 +450,12 @@ throw(anna::RuntimeException) { oamModule.count(OamModule::Counter::AnswerReceivedUnknown); oamModule.count(OamModule::Counter::AnswerReceivedOnServerSessionUnknown); oamModule.activateAlarm(OamModule::Alarm::AnswerReceivedOnServerSessionUnknown); + + // application message counters + ApplicationMessageOamModule::instantiate().count(cid.first, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Answer_UnknownReceived_AsServer); + eventUnknownResponse(db); + string msg(asString()); msg += anna::functions::asString(" | Response received from client, for non registered context (HopByHop: %u)", hopByHop); throw anna::RuntimeException(msg, ANNA_FILE_LOCATION); @@ -490,7 +501,12 @@ throw(anna::RuntimeException) { ); diameter::codec::functions::setHopByHop((anna::DataBlock&)db, response->getRequest()->getRequestHopByHop()); diameter::codec::functions::setEndToEnd((anna::DataBlock&)db, response->getRequest()->getRequestEndToEnd()); + + // application message counters + ApplicationMessageOamModule::instantiate().count(cid.first, anna::diameter::codec::functions::getApplicationId(db), ApplicationMessageOamModule::Counter::Answer_Received_AsServer); + eventResponse(*response); + } catch(anna::RuntimeException& ex) { ex.trace(); } @@ -696,8 +712,10 @@ void ServerSession::updateOutgoingActivityTime(void) throw() { //------------------------------------------------------------------------------ //----------------------------------------------- ServerSession::countSendings() //------------------------------------------------------------------------------ -void ServerSession::countSendings(const diameter::CommandId & cid, bool ok)throw() { +void ServerSession::countSendings(const diameter::CommandId & cid, unsigned int aid, bool ok)throw() { OamModule &oamModule = OamModule::instantiate(); + ApplicationMessageOamModule &appMsgOamModule = ApplicationMessageOamModule::instantiate(); + bool isRequest = cid.second; if(ok) { @@ -710,6 +728,10 @@ void ServerSession::countSendings(const diameter::CommandId & cid, bool ok)throw else if(cid == helpers::base::COMMANDID__Device_Watchdog_Request) oamModule.count(OamModule::Counter::DWRSentOK); // not usual else if(cid == helpers::base::COMMANDID__Disconnect_Peer_Answer) oamModule.count(OamModule::Counter::DPASentOK); else if(cid == helpers::base::COMMANDID__Disconnect_Peer_Request) oamModule.count(OamModule::Counter::DPRSentOK); + // Application messages: + else { + appMsgOamModule.count(cid.first, aid, isRequest ? ApplicationMessageOamModule::Counter::Request_SentOK_AsServer : ApplicationMessageOamModule::Counter::Answer_SentOK_AsServer); + } } else { // Main counters: oamModule.count(isRequest ? OamModule::Counter::RequestSentNOK : OamModule::Counter::AnswerSentNOK); @@ -720,6 +742,10 @@ void ServerSession::countSendings(const diameter::CommandId & cid, bool ok)throw else if(cid == helpers::base::COMMANDID__Device_Watchdog_Request) oamModule.count(OamModule::Counter::DWRSentNOK); // not usual else if(cid == helpers::base::COMMANDID__Disconnect_Peer_Answer) oamModule.count(OamModule::Counter::DPASentNOK); else if(cid == helpers::base::COMMANDID__Disconnect_Peer_Request) oamModule.count(OamModule::Counter::DPRSentNOK); + // Application messages: + else { + appMsgOamModule.count(cid.first, aid, isRequest ? ApplicationMessageOamModule::Counter::Request_SentNOK_AsServer : ApplicationMessageOamModule::Counter::Answer_SentNOK_AsServer); + } } } -- 2.20.1