From 7cb5ff670a4a55af11faea5809d8cd810590030a Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Sat, 26 May 2018 19:13:47 +0200 Subject: [PATCH] - IEC 61850 server: added support to configure report buffer at runtime - IEC 61850 server: new IedServerConfig type and new IedServer constructor --- CHANGELOG | 6 ++ .../server_example_basic_io.c | 14 ++++- src/CMakeLists.txt | 1 + .../inc/libiec61850_platform_includes.h | 2 +- src/iec61850/inc/iec61850_common.h | 3 +- src/iec61850/inc/iec61850_server.h | 55 ++++++++++++++++++- src/iec61850/inc_private/ied_server_private.h | 2 +- src/iec61850/inc_private/mms_mapping.h | 7 +-- src/iec61850/inc_private/reporting.h | 2 +- src/iec61850/server/impl/ied_server.c | 22 ++++++-- src/iec61850/server/impl/ied_server_config.c | 55 +++++++++++++++++++ src/iec61850/server/mms_mapping/mms_mapping.c | 9 +-- src/iec61850/server/mms_mapping/reporting.c | 34 ++++++++---- src/vs/libiec61850-wo-goose.def | 7 ++- src/vs/libiec61850.def | 7 ++- 15 files changed, 187 insertions(+), 39 deletions(-) create mode 100644 src/iec61850/server/impl/ied_server_config.c diff --git a/CHANGELOG b/CHANGELOG index d3390515..d152b05a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +Changes to version 1.2.2 +------------------------ + +- IEC 61850 server: added support to configure report buffer at runtime +- IEC 61850 server: new IedServerConfig type and new IedServer constructor + Changes to version 1.2.1 ------------------------ diff --git a/examples/server_example_basic_io/server_example_basic_io.c b/examples/server_example_basic_io/server_example_basic_io.c index 14c44e32..218a7466 100644 --- a/examples/server_example_basic_io/server_example_basic_io.c +++ b/examples/server_example_basic_io/server_example_basic_io.c @@ -83,7 +83,17 @@ main(int argc, char** argv) { printf("Using libIEC61850 version %s\n", LibIEC61850_getVersionString()); - iedServer = IedServer_create(&iedModel); + /* Create new server configuration object */ + IedServerConfig config = IedServerConfig_create(); + + /* Set buffer size for buffered report control blocks to 200000 bytes */ + IedServerConfig_setReportBufferSize(config, 200000); + + /* Create a new IEC 61850 server instance */ + iedServer = IedServer_createWithConfig(&iedModel, NULL, config); + + /* configuration object is no longer required */ + IedServerConfig_destroy(config); /* Set the base path for the MMS file services */ MmsServer mmsServer = IedServer_getMmsServer(iedServer); @@ -108,7 +118,7 @@ main(int argc, char** argv) IedServer_setConnectionIndicationHandler(iedServer, (IedConnectionIndicationHandler) connectionHandler, NULL); - /* MMS server will be instructed to start listening to client connections. */ + /* MMS server will be instructed to start listening for client connections. */ IedServer_start(iedServer, 102); if (!IedServer_isRunning(iedServer)) { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 81fbd3cc..03d77fab 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -66,6 +66,7 @@ set (lib_common_SRCS ./iec61850/client/ied_connection.c ./iec61850/common/iec61850_common.c ./iec61850/server/impl/ied_server.c +./iec61850/server/impl/ied_server_config.c ./iec61850/server/impl/client_connection.c ./iec61850/server/model/model.c ./iec61850/server/model/dynamic_model.c diff --git a/src/common/inc/libiec61850_platform_includes.h b/src/common/inc/libiec61850_platform_includes.h index 5ca0f523..d25ac59c 100644 --- a/src/common/inc/libiec61850_platform_includes.h +++ b/src/common/inc/libiec61850_platform_includes.h @@ -15,7 +15,7 @@ #include "platform_endian.h" -#define LIBIEC61850_VERSION "1.2.1" +#define LIBIEC61850_VERSION "1.2.2" #ifndef CONFIG_DEFAULT_MMS_VENDOR_NAME #define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com" diff --git a/src/iec61850/inc/iec61850_common.h b/src/iec61850/inc/iec61850_common.h index 5b5a14e4..d8de6a3e 100644 --- a/src/iec61850/inc/iec61850_common.h +++ b/src/iec61850/inc/iec61850_common.h @@ -421,12 +421,11 @@ Timestamp_toMmsValue(Timestamp* self, MmsValue* mmsValue); /** * \brief Get the version of the library as string * - * \return the version of the library (e.g. "0.8.3") + * \return the version of the library (e.g. "1.2.2") */ char* LibIEC61850_getVersionString(void); - /** @} */ /**@}*/ diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h index eadafaef..30f57201 100644 --- a/src/iec61850/inc/iec61850_server.h +++ b/src/iec61850/inc/iec61850_server.h @@ -3,7 +3,7 @@ * * IEC 61850 server API for libiec61850. * - * Copyright 2013, 2014 Michael Zillgith + * Copyright 2013-2018 Michael Zillgith * * This file is part of libIEC61850. * @@ -41,6 +41,49 @@ extern "C" { #include "hal_filesystem.h" #include "iec61850_config_file_parser.h" +/** + * \brief Configuration object to configure IEC 61850 stack features + */ +typedef struct sIedServerConfig* IedServerConfig; + +struct sIedServerConfig +{ + /** size of the report buffer associated with a buffered report control block */ + int reportBufferSize; +}; + +/** + * \brief Create a new configuration object + * + * \return a new configuration object with default configuration values + */ +IedServerConfig +IedServerConfig_create(void); + +/** + * \brief Destroy the configuration object + */ +void +IedServerConfig_destroy(IedServerConfig self); + +/** + * \brief Set the report buffer size for buffered reporting + * + * \param reportBufferSize the buffer size for each buffered report control block + */ +void +IedServerConfig_setReportBufferSize(IedServerConfig self, int reportBufferSize); + +/** + * \brief Gets the report buffer size for buffered reporting + * + * \return the buffer size for each buffered report control block + */ +int +IedServerConfig_getReportBufferSize(IedServerConfig self); + + + /** * An opaque handle for an IED server instance */ @@ -79,6 +122,16 @@ IedServer_create(IedModel* dataModel); IedServer IedServer_createWithTlsSupport(IedModel* dataModel, TLSConfiguration tlsConfiguration); +/** + * \brief Create new new IedServer with extended configurations parameters + * + * \param dataModel reference to the IedModel data structure to be used as IEC 61850 data model of the device + * \param tlsConfiguration TLS configuration object, or NULL to not use TLS + * \param serverConfiguration IED server configuration object for advanced server configuration + */ +IedServer +IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguration, IedServerConfig serverConfiguration); + /** * \brief Destroy an IedServer instance and release all resources (memory, TCP sockets) * diff --git a/src/iec61850/inc_private/ied_server_private.h b/src/iec61850/inc_private/ied_server_private.h index a6308267..d78702cc 100644 --- a/src/iec61850/inc_private/ied_server_private.h +++ b/src/iec61850/inc_private/ied_server_private.h @@ -3,7 +3,7 @@ * * Library private function definitions for IedServer. * - * Copyright 2013 Michael Zillgith + * Copyright 2013-2018 Michael Zillgith * * This file is part of libIEC61850. * diff --git a/src/iec61850/inc_private/mms_mapping.h b/src/iec61850/inc_private/mms_mapping.h index ec6240ad..5c033535 100644 --- a/src/iec61850/inc_private/mms_mapping.h +++ b/src/iec61850/inc_private/mms_mapping.h @@ -1,7 +1,7 @@ /* * mms_mapping.h * - * Copyright 2013-2016 Michael Zillgith + * Copyright 2013-2018 Michael Zillgith * * This file is part of libIEC61850. * @@ -46,7 +46,7 @@ typedef enum { typedef struct sMmsMapping MmsMapping; MmsMapping* -MmsMapping_create(IedModel* model); +MmsMapping_create(IedModel* model, IedServer iedServer); MmsDevice* MmsMapping_getMmsDeviceModel(MmsMapping* mapping); @@ -138,9 +138,6 @@ MmsMapping_ObjectReferenceToVariableAccessSpec(char* objectReference); char* MmsMapping_varAccessSpecToObjectReference(MmsVariableAccessSpecification* varAccessSpec); -void -MmsMapping_setIedServer(MmsMapping* self, IedServer iedServer); - void MmsMapping_setConnectionIndicationHandler(MmsMapping* self, IedConnectionIndicationHandler handler, void* parameter); diff --git a/src/iec61850/inc_private/reporting.h b/src/iec61850/inc_private/reporting.h index dce535a4..2dddb257 100644 --- a/src/iec61850/inc_private/reporting.h +++ b/src/iec61850/inc_private/reporting.h @@ -97,7 +97,7 @@ typedef struct { } ReportControl; ReportControl* -ReportControl_create(bool buffered, LogicalNode* parentLN); +ReportControl_create(bool buffered, LogicalNode* parentLN, int reportBufferSize); void ReportControl_destroy(ReportControl* self); diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c index c219b9a0..28081980 100644 --- a/src/iec61850/server/impl/ied_server.c +++ b/src/iec61850/server/impl/ied_server.c @@ -391,8 +391,9 @@ updateDataSetsWithCachedValues(IedServer self) } } + IedServer -IedServer_createWithTlsSupport(IedModel* dataModel, TLSConfiguration tlsConfiguration) +IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguration, IedServerConfig serverConfiguration) { IedServer self = (IedServer) GLOBAL_CALLOC(1, sizeof(struct sIedServer)); @@ -407,7 +408,14 @@ IedServer_createWithTlsSupport(IedModel* dataModel, TLSConfiguration tlsConfigur self->dataModelLock = Semaphore_create(1); #endif - self->mmsMapping = MmsMapping_create(dataModel); +#if (CONFIG_IEC61850_REPORT_SERVICE == 1) + if (serverConfiguration) + self->reportBufferSize = serverConfiguration->reportBufferSize; + else + self->reportBufferSize = CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE; +#endif + + self->mmsMapping = MmsMapping_create(dataModel, self); self->mmsDevice = MmsMapping_getMmsDeviceModel(self->mmsMapping); @@ -417,8 +425,6 @@ IedServer_createWithTlsSupport(IedModel* dataModel, TLSConfiguration tlsConfigur MmsMapping_installHandlers(self->mmsMapping); - MmsMapping_setIedServer(self->mmsMapping, self); - createMmsServerCache(self); dataModel->initializer(); @@ -447,7 +453,13 @@ IedServer_createWithTlsSupport(IedModel* dataModel, TLSConfiguration tlsConfigur IedServer IedServer_create(IedModel* dataModel) { - return IedServer_createWithTlsSupport(dataModel, NULL); + return IedServer_createWithConfig(dataModel, NULL, NULL); +} + +IedServer +IedServer_createWithTlsSupport(IedModel* dataModel, TLSConfiguration tlsConfiguration) +{ + return IedServer_createWithConfig(dataModel, tlsConfiguration, NULL); } void diff --git a/src/iec61850/server/impl/ied_server_config.c b/src/iec61850/server/impl/ied_server_config.c new file mode 100644 index 00000000..4f0f5072 --- /dev/null +++ b/src/iec61850/server/impl/ied_server_config.c @@ -0,0 +1,55 @@ +/* + * ied_server_config.c + * + * Copyright 2018 Michael Zillgith + * + * This file is part of libIEC61850. + * + * libIEC61850 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 3 of the License, or + * (at your option) any later version. + * + * libIEC61850 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libIEC61850. If not, see . + * + * See COPYING file for the complete license text. + */ + +#include "iec61850_server.h" +#include "libiec61850_platform_includes.h" + +IedServerConfig +IedServerConfig_create() +{ + IedServerConfig self = (IedServerConfig) GLOBAL_MALLOC(sizeof(struct sIedServerConfig)); + + if (self) { + self->reportBufferSize = CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE; + } + + return self; +} + +void +IedServerConfig_destroy(IedServerConfig self) +{ + GLOBAL_FREEMEM(self); +} + +void +IedServerConfig_setReportBufferSize(IedServerConfig self, int reportBufferSize) +{ + self->reportBufferSize = reportBufferSize; +} + +int +IedServerConfig_getReportBufferSize(IedServerConfig self) +{ + return self->reportBufferSize; +} diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c index 7cf2225b..957c3429 100644 --- a/src/iec61850/server/mms_mapping/mms_mapping.c +++ b/src/iec61850/server/mms_mapping/mms_mapping.c @@ -1272,11 +1272,12 @@ createMmsModelFromIedModel(MmsMapping* self, IedModel* iedModel) } MmsMapping* -MmsMapping_create(IedModel* model) +MmsMapping_create(IedModel* model, IedServer iedServer) { MmsMapping* self = (MmsMapping*) GLOBAL_CALLOC(1, sizeof(struct sMmsMapping)); self->model = model; + self->iedServer = iedServer; #if (CONFIG_IEC61850_REPORT_SERVICE == 1) self->reportControls = LinkedList_create(); @@ -2564,12 +2565,6 @@ MmsMapping_installHandlers(MmsMapping* self) MmsServer_installVariableListChangedHandler(self->mmsServer, variableListChangedHandler, (void*) self); } -void -MmsMapping_setIedServer(MmsMapping* self, IedServer iedServer) -{ - self->iedServer = iedServer; -} - void MmsMapping_setConnectionIndicationHandler(MmsMapping* self, IedConnectionIndicationHandler handler, void* parameter) { diff --git a/src/iec61850/server/mms_mapping/reporting.c b/src/iec61850/server/mms_mapping/reporting.c index 642d06fc..5edf1504 100644 --- a/src/iec61850/server/mms_mapping/reporting.c +++ b/src/iec61850/server/mms_mapping/reporting.c @@ -35,6 +35,7 @@ #include "mms_value_internal.h" #include "conversions.h" #include "reporting.h" +#include "ied_server_private.h" #include #ifndef DEBUG_IED_SERVER @@ -62,16 +63,25 @@ static ReportBuffer* -ReportBuffer_create(void) +ReportBuffer_create(int bufferSize) { ReportBuffer* self = (ReportBuffer*) GLOBAL_MALLOC(sizeof(ReportBuffer)); - self->lastEnqueuedReport = NULL; - self->oldestReport = NULL; - self->nextToTransmit = NULL; - self->memoryBlockSize = CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE; - self->memoryBlock = (uint8_t*) GLOBAL_MALLOC(self->memoryBlockSize); - self->reportsCount = 0; - self->isOverflow = true; + + if (self) { + self->lastEnqueuedReport = NULL; + self->oldestReport = NULL; + self->nextToTransmit = NULL; + self->reportsCount = 0; + self->isOverflow = true; + + self->memoryBlockSize = bufferSize; + self->memoryBlock = (uint8_t*) GLOBAL_MALLOC(self->memoryBlockSize); + + if (self->memoryBlock == NULL) { + GLOBAL_FREEMEM(self); + self = NULL; + } + } return self; } @@ -84,7 +94,7 @@ ReportBuffer_destroy(ReportBuffer* self) } ReportControl* -ReportControl_create(bool buffered, LogicalNode* parentLN) +ReportControl_create(bool buffered, LogicalNode* parentLN, int reportBufferSize) { ReportControl* self = (ReportControl*) GLOBAL_MALLOC(sizeof(ReportControl)); self->name = NULL; @@ -120,7 +130,7 @@ ReportControl_create(bool buffered, LogicalNode* parentLN) self->lastEntryId = 0; if (buffered) { - self->reportBuffer = ReportBuffer_create(); + self->reportBuffer = ReportBuffer_create(reportBufferSize); } return self; @@ -1156,7 +1166,7 @@ Reporting_createMmsBufferedRCBs(MmsMapping* self, MmsDomain* domain, int currentReport = 0; while (currentReport < reportsCount) { - ReportControl* rc = ReportControl_create(true, logicalNode); + ReportControl* rc = ReportControl_create(true, logicalNode, self->iedServer->reportBufferSize); rc->domain = domain; @@ -1193,7 +1203,7 @@ Reporting_createMmsUnbufferedRCBs(MmsMapping* self, MmsDomain* domain, int currentReport = 0; while (currentReport < reportsCount) { - ReportControl* rc = ReportControl_create(false, logicalNode); + ReportControl* rc = ReportControl_create(false, logicalNode, self->iedServer->reportBufferSize); rc->domain = domain; diff --git a/src/vs/libiec61850-wo-goose.def b/src/vs/libiec61850-wo-goose.def index f6c247ea..7c866d42 100644 --- a/src/vs/libiec61850-wo-goose.def +++ b/src/vs/libiec61850-wo-goose.def @@ -580,4 +580,9 @@ EXPORTS CDC_VSS_create CDC_VSG_create Timestamp_createFromByteArray - IedModel_getDeviceByIndex \ No newline at end of file + IedModel_getDeviceByIndex + IedServerConfig_create + IedServerConfig_destroy + IedServerConfig_setReportBufferSize + IedServerConfig_getReportBufferSize + IedServer_createWithConfig \ No newline at end of file diff --git a/src/vs/libiec61850.def b/src/vs/libiec61850.def index 6ba5d303..c9190c50 100644 --- a/src/vs/libiec61850.def +++ b/src/vs/libiec61850.def @@ -707,4 +707,9 @@ EXPORTS SVPublisher_ASDU_setQuality Timestamp_createFromByteArray IedModel_getDeviceByIndex - SVReceiver_enableDestAddrCheck \ No newline at end of file + SVReceiver_enableDestAddrCheck + IedServerConfig_create + IedServerConfig_destroy + IedServerConfig_setReportBufferSize + IedServerConfig_getReportBufferSize + IedServer_createWithConfig \ No newline at end of file