- IEC 61850 server: optimized dynamic memory management in control handling; memory will be initialized at server start

pull/72/head
Michael Zillgith 7 years ago
parent 6618093f7a
commit 713ca54cd0

@ -25,29 +25,89 @@
#define CONTROL_H_ #define CONTROL_H_
#include "iec61850_model.h" #include "iec61850_model.h"
#include "iec61850_server.h"
#include "mms_server_connection.h" #include "mms_server_connection.h"
#include "mms_device_model.h" #include "mms_device_model.h"
#include "iec61850_server.h"
#include "mms_mapping_internal.h"
#include "mms_client_connection.h"
#include "libiec61850_platform_includes.h"
typedef struct sControlObject ControlObject; typedef struct sControlObject ControlObject;
ControlObject* struct sControlObject
ControlObject_create(IedServer iedServer, MmsDomain* domain, char* lnName, char* name); {
MmsDomain* mmsDomain;
IedServer iedServer;
char* lnName;
char* name;
void int state;
ControlObject_destroy(ControlObject* self);
void #if (CONFIG_MMS_THREADLESS_STACK != 1)
ControlObject_setOper(ControlObject* self, MmsValue* oper); Semaphore stateLock;
#endif
void MmsValue* mmsValue;
ControlObject_setCancel(ControlObject* self, MmsValue* cancel); MmsVariableSpecification* typeSpec;
MmsValue* oper;
MmsValue* sbo;
MmsValue* sbow;
MmsValue* cancel;
MmsValue* ctlVal;
MmsValue* ctlNum;
MmsValue* origin;
MmsValue* timestamp;
char ctlObjectName[130];
/* for LastAppIError */
MmsValue* error;
MmsValue* addCause;
bool selected;
uint64_t selectTime;
uint32_t selectTimeout;
MmsValue* sboClass;
MmsValue* sboTimeout;
bool timeActivatedOperate;
uint64_t operateTime;
bool operateOnce;
MmsServerConnection mmsConnection;
MmsValue* emptyString;
uint32_t ctlModel;
bool testMode;
bool interlockCheck;
bool synchroCheck;
uint32_t operateInvokeId;
ControlHandler operateHandler;
void* operateHandlerParameter;
ControlPerformCheckHandler checkHandler;
void* checkHandlerParameter;
ControlWaitForExecutionHandler waitForExecutionHandler;
void* waitForExecutionHandlerParameter;
};
ControlObject*
ControlObject_create(IedServer iedServer, MmsDomain* domain, char* lnName, char* name);
void void
ControlObject_setSBO(ControlObject* self, MmsValue* sbo); ControlObject_initialize(ControlObject* self);
void void
ControlObject_setSBOw(ControlObject* self, MmsValue* sbow); ControlObject_destroy(ControlObject* self);
void void
ControlObject_setMmsValue(ControlObject* self, MmsValue* value); ControlObject_setMmsValue(ControlObject* self, MmsValue* value);
@ -61,21 +121,6 @@ ControlObject_setTypeSpec(ControlObject* self, MmsVariableSpecification* typeSpe
MmsVariableSpecification* MmsVariableSpecification*
ControlObject_getTypeSpec(ControlObject* self); ControlObject_getTypeSpec(ControlObject* self);
MmsValue*
ControlObject_getOper(ControlObject* self);
MmsValue*
ControlObject_getSBOw(ControlObject* self);
MmsValue*
ControlObject_getSBO(ControlObject* self);
MmsValue*
ControlObject_getCancel(ControlObject* self);
void
ControlObject_setCtlVal(ControlObject* self, MmsValue* ctlVal);
char* char*
ControlObject_getName(ControlObject* self); ControlObject_getName(ControlObject* self);

@ -49,6 +49,9 @@ MmsMapping_create(IedModel* model, IedServer iedServer);
MmsDevice* MmsDevice*
MmsMapping_getMmsDeviceModel(MmsMapping* mapping); MmsMapping_getMmsDeviceModel(MmsMapping* mapping);
void
MmsMapping_initializeControlObjects(MmsMapping* self);
void void
MmsMapping_configureSettingGroups(MmsMapping* self); MmsMapping_configureSettingGroups(MmsMapping* self);

@ -119,18 +119,13 @@ createControlObjects(IedServer self, MmsDomain* domain, char* lnName, MmsVariabl
ControlObject_setTypeSpec(controlObject, coSpec); ControlObject_setTypeSpec(controlObject, coSpec);
MmsValue* operVal = MmsValue_getElement(structure, operIndex); controlObject->oper = MmsValue_getElement(structure, operIndex);
ControlObject_setOper(controlObject, operVal);
if (hasCancel) { if (hasCancel)
MmsValue* cancelVal = MmsValue_getElement(structure, cancelIndex); controlObject->cancel = MmsValue_getElement(structure, cancelIndex);
ControlObject_setCancel(controlObject, cancelVal);
}
if (hasSBOw) { if (hasSBOw)
MmsValue* sbowVal = MmsValue_getElement(structure, sBOwIndex); controlObject->sbow = MmsValue_getElement(structure, sBOwIndex);
ControlObject_setSBOw(controlObject, sbowVal);
}
MmsMapping_addControlObject(mapping, controlObject); MmsMapping_addControlObject(mapping, controlObject);
} }
@ -457,6 +452,8 @@ IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguratio
/* default write access policy allows access to SP, SE and SV FCDAs but denies access to DC and CF FCDAs */ /* default write access policy allows access to SP, SE and SV FCDAs but denies access to DC and CF FCDAs */
self->writeAccessPolicies = ALLOW_WRITE_ACCESS_SP | ALLOW_WRITE_ACCESS_SV | ALLOW_WRITE_ACCESS_SE; self->writeAccessPolicies = ALLOW_WRITE_ACCESS_SP | ALLOW_WRITE_ACCESS_SV | ALLOW_WRITE_ACCESS_SE;
MmsMapping_initializeControlObjects(self->mmsMapping);
#if (CONFIG_IEC61850_REPORT_SERVICE == 1) #if (CONFIG_IEC61850_REPORT_SERVICE == 1)
Reporting_activateBufferedReports(self->mmsMapping); Reporting_activateBufferedReports(self->mmsMapping);
#endif #endif

@ -1,7 +1,7 @@
/* /*
* control.c * control.c
* *
* Copyright 2013 Michael Zillgith * Copyright 2013-2018 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -22,17 +22,12 @@
*/ */
#include "control.h" #include "control.h"
#include "mms_mapping.h"
#include "mms_mapping_internal.h"
#include "mms_client_connection.h"
#include "mms_mapping.h"
#include "iec61850_server.h"
#include "ied_server_private.h" #include "ied_server_private.h"
#include "mms_value_internal.h" #include "mms_value_internal.h"
#include "libiec61850_platform_includes.h"
#if (CONFIG_IEC61850_CONTROL_SERVICE == 1) #if (CONFIG_IEC61850_CONTROL_SERVICE == 1)
#ifndef DEBUG_IED_SERVER #ifndef DEBUG_IED_SERVER
@ -51,71 +46,6 @@
#define STATE_WAIT_FOR_EXECUTION 4 #define STATE_WAIT_FOR_EXECUTION 4
#define STATE_OPERATE 5 #define STATE_OPERATE 5
struct sControlObject
{
MmsDomain* mmsDomain;
IedServer iedServer;
char* lnName;
char* name;
int state;
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore stateLock;
#endif
MmsValue* mmsValue;
MmsVariableSpecification* typeSpec;
MmsValue* oper;
MmsValue* sbo;
MmsValue* sbow;
MmsValue* cancel;
MmsValue* ctlVal;
MmsValue* ctlNum;
MmsValue* origin;
MmsValue* timestamp;
char* ctlObjectName;
/* for LastAppIError */
MmsValue* error;
MmsValue* addCause;
bool selected;
uint64_t selectTime;
uint32_t selectTimeout;
MmsValue* sboClass;
MmsValue* sboTimeout;
bool timeActivatedOperate;
uint64_t operateTime;
bool operateOnce;
MmsServerConnection mmsConnection;
MmsValue* emptyString;
bool initialized;
uint32_t ctlModel;
bool testMode;
bool interlockCheck;
bool synchroCheck;
uint32_t operateInvokeId;
ControlHandler operateHandler;
void* operateHandlerParameter;
ControlPerformCheckHandler checkHandler;
void* checkHandlerParameter;
ControlWaitForExecutionHandler waitForExecutionHandler;
void* waitForExecutionHandlerParameter;
};
void void
ControlObject_sendLastApplError(ControlObject* self, MmsServerConnection connection, char* ctlVariable, int error, ControlObject_sendLastApplError(ControlObject* self, MmsServerConnection connection, char* ctlVariable, int error,
ControlAddCause addCause, MmsValue* ctlNum, MmsValue* origin, bool handlerMode); ControlAddCause addCause, MmsValue* ctlNum, MmsValue* origin, bool handlerMode);
@ -183,78 +113,68 @@ updateSboTimeoutValue(ControlObject* self)
static void static void
initialize(ControlObject* self) initialize(ControlObject* self)
{ {
if (!(self->initialized)) { MmsServer mmsServer = IedServer_getMmsServer(self->iedServer);
MmsServer mmsServer = IedServer_getMmsServer(self->iedServer);
self->emptyString = MmsValue_newVisibleString(NULL); self->emptyString = MmsValue_newVisibleString(NULL);
char* ctlModelName = StringUtils_createString(4, self->lnName, "$CF$", self->name, "$ctlModel"); char strBuf[129];
if (DEBUG_IED_SERVER) char* ctlModelName = StringUtils_createStringInBuffer(strBuf, 4, self->lnName, "$CF$", self->name, "$ctlModel");
printf("initialize control for %s\n", ctlModelName);
MmsValue* ctlModel = MmsServer_getValueFromCache(mmsServer,
self->mmsDomain, ctlModelName);
if (ctlModel == NULL) {
if (DEBUG_IED_SERVER)
printf("No control model found for variable %s\n", ctlModelName);
}
GLOBAL_FREEMEM(ctlModelName); if (DEBUG_IED_SERVER)
printf("initialize control for %s\n", ctlModelName);
char* sboClassName = StringUtils_createString(4, self->lnName, "$CF$", self->name, "$sboClass"); MmsValue* ctlModel = MmsServer_getValueFromCache(mmsServer,
self->mmsDomain, ctlModelName);
self->sboClass = MmsServer_getValueFromCache(mmsServer, self->mmsDomain, sboClassName); if (ctlModel == NULL) {
if (DEBUG_IED_SERVER)
printf("No control model found for variable %s\n", ctlModelName);
}
GLOBAL_FREEMEM(sboClassName); char* sboClassName = StringUtils_createStringInBuffer(strBuf, 4, self->lnName, "$CF$", self->name, "$sboClass");
self->ctlObjectName = (char*) GLOBAL_MALLOC(130); self->sboClass = MmsServer_getValueFromCache(mmsServer, self->mmsDomain, sboClassName);
StringUtils_createStringInBuffer(self->ctlObjectName, 5, MmsDomain_getName(self->mmsDomain), "/", StringUtils_createStringInBuffer(self->ctlObjectName, 5, MmsDomain_getName(self->mmsDomain), "/",
self->lnName, "$CO$", self->name); self->lnName, "$CO$", self->name);
self->error = MmsValue_newIntegerFromInt32(0); self->error = MmsValue_newIntegerFromInt32(0);
self->addCause = MmsValue_newIntegerFromInt32(0); self->addCause = MmsValue_newIntegerFromInt32(0);
if (ctlModel != NULL) { if (ctlModel != NULL) {
uint32_t ctlModelVal = MmsValue_toInt32(ctlModel); uint32_t ctlModelVal = MmsValue_toInt32(ctlModel);
self->ctlModel = ctlModelVal; self->ctlModel = ctlModelVal;
if (DEBUG_IED_SERVER) if (DEBUG_IED_SERVER)
printf(" ctlModel: %i\n", ctlModelVal); printf(" ctlModel: %i\n", ctlModelVal);
if ((ctlModelVal == 2) || (ctlModelVal == 4)) { /* SBO */ if ((ctlModelVal == 2) || (ctlModelVal == 4)) { /* SBO */
char* sboTimeoutName = StringUtils_createString(4, self->lnName, "$CF$", self->name, "$sboTimeout");
char* controlObjectReference = StringUtils_createString(6, self->mmsDomain->domainName, "/", self->lnName, "$",
self->name, "$SBO");
self->sbo = MmsValue_newVisibleString(controlObjectReference); char* controlObjectReference = StringUtils_createStringInBuffer(strBuf, 6, self->mmsDomain->domainName,
"/", self->lnName, "$", self->name, "$SBO");
self->sboTimeout = MmsServer_getValueFromCache(mmsServer, self->sbo = MmsValue_newVisibleString(controlObjectReference);
self->mmsDomain, sboTimeoutName);
updateSboTimeoutValue(self); char* sboTimeoutName = StringUtils_createStringInBuffer(strBuf, 4, self->lnName, "$CF$", self->name, "$sboTimeout");
setState(self, STATE_UNSELECTED); self->sboTimeout = MmsServer_getValueFromCache(mmsServer,
self->mmsDomain, sboTimeoutName);
if (DEBUG_IED_SERVER) updateSboTimeoutValue(self);
printf("timeout for %s is %i\n", sboTimeoutName, self->selectTimeout);
GLOBAL_FREEMEM(controlObjectReference); setState(self, STATE_UNSELECTED);
GLOBAL_FREEMEM(sboTimeoutName);
}
else {
self->sbo = MmsValue_newVisibleString(NULL);
setState(self, STATE_READY); if (DEBUG_IED_SERVER)
} printf("timeout for %s is %i\n", sboTimeoutName, self->selectTimeout);
} }
else {
self->sbo = MmsValue_newVisibleString(NULL);
self->initialized = true; setState(self, STATE_READY);
}
} }
} }
@ -467,6 +387,12 @@ exit_function:
return self; return self;
} }
void
ControlObject_initialize(ControlObject* self)
{
initialize(self);
}
void void
ControlObject_destroy(ControlObject* self) ControlObject_destroy(ControlObject* self)
{ {
@ -479,9 +405,6 @@ ControlObject_destroy(ControlObject* self)
if (self->emptyString != NULL) if (self->emptyString != NULL)
MmsValue_delete(self->emptyString); MmsValue_delete(self->emptyString);
if (self->ctlObjectName != NULL)
GLOBAL_FREEMEM(self->ctlObjectName);
if (self->error != NULL) if (self->error != NULL)
MmsValue_delete(self->error); MmsValue_delete(self->error);
@ -508,36 +431,6 @@ ControlObject_destroy(ControlObject* self)
GLOBAL_FREEMEM(self); GLOBAL_FREEMEM(self);
} }
void
ControlObject_setOper(ControlObject* self, MmsValue* oper)
{
self->oper = oper;
}
void
ControlObject_setCancel(ControlObject* self, MmsValue* cancel)
{
self->cancel = cancel;
}
void
ControlObject_setSBOw(ControlObject* self, MmsValue* sbow)
{
self->sbow = sbow;
}
void
ControlObject_setSBO(ControlObject* self, MmsValue* sbo)
{
self->sbo = sbo;
}
void
ControlObject_setCtlVal(ControlObject* self, MmsValue* ctlVal)
{
self->ctlVal = ctlVal;
}
char* char*
ControlObject_getName(ControlObject* self) ControlObject_getName(ControlObject* self)
{ {
@ -556,30 +449,6 @@ ControlObject_getDomain(ControlObject* self)
return self->mmsDomain; return self->mmsDomain;
} }
MmsValue*
ControlObject_getOper(ControlObject* self)
{
return self->oper;
}
MmsValue*
ControlObject_getSBOw(ControlObject* self)
{
return self->sbow;
}
MmsValue*
ControlObject_getSBO(ControlObject* self)
{
return self->sbo;
}
MmsValue*
ControlObject_getCancel(ControlObject* self)
{
return self->cancel;
}
void void
ControlObject_setMmsValue(ControlObject* self, MmsValue* value) ControlObject_setMmsValue(ControlObject* self, MmsValue* value)
{ {
@ -1122,13 +991,13 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
if (controlObject != NULL) { if (controlObject != NULL) {
initialize(controlObject); //initialize(controlObject);
if (varName != NULL) { if (varName != NULL) {
if (strcmp(varName, "Oper") == 0) if (strcmp(varName, "Oper") == 0)
value = ControlObject_getOper(controlObject); value = controlObject->oper;
else if (strcmp(varName, "SBOw") == 0) else if (strcmp(varName, "SBOw") == 0)
value = ControlObject_getSBOw(controlObject); value = controlObject->sbow;
else if (strcmp(varName, "SBO") == 0) { else if (strcmp(varName, "SBO") == 0) {
if (controlObject->ctlModel == 2) { if (controlObject->ctlModel == 2) {
@ -1153,7 +1022,7 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
if (checkResult == CONTROL_ACCEPTED) { if (checkResult == CONTROL_ACCEPTED) {
selectObject(controlObject, currentTime, connection); selectObject(controlObject, currentTime, connection);
value = ControlObject_getSBO(controlObject); value = controlObject->sbo;
} }
} }
@ -1162,12 +1031,12 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
if (DEBUG_IED_SERVER) if (DEBUG_IED_SERVER)
printf("IED_SERVER: select not applicable for control model %i\n", controlObject->ctlModel); printf("IED_SERVER: select not applicable for control model %i\n", controlObject->ctlModel);
value = ControlObject_getSBO(controlObject); value = controlObject->sbo;
} }
} }
else if (strcmp(varName, "Cancel") == 0) else if (strcmp(varName, "Cancel") == 0)
value = ControlObject_getCancel(controlObject); value = controlObject->cancel;
else { else {
value = MmsValue_getSubElement(ControlObject_getMmsValue(controlObject), value = MmsValue_getSubElement(ControlObject_getMmsValue(controlObject),
ControlObject_getTypeSpec(controlObject), varName); ControlObject_getTypeSpec(controlObject), varName);
@ -1289,7 +1158,7 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
goto free_and_return; goto free_and_return;
} }
initialize(controlObject); //initialize(controlObject);
if (strcmp(varName, "SBOw") == 0) { /* select with value */ if (strcmp(varName, "SBOw") == 0) { /* select with value */

@ -599,6 +599,20 @@ MmsMapping_checkForSettingGroupReservationTimeouts(MmsMapping* self, uint64_t cu
} }
} }
void
MmsMapping_initializeControlObjects(MmsMapping* self)
{
LinkedList element = LinkedList_getNext(self->controlObjects);
while (element) {
ControlObject* controlObject = (ControlObject*) LinkedList_getData(element);
ControlObject_initialize(controlObject);
element = LinkedList_getNext(element);
}
}
void void
MmsMapping_configureSettingGroups(MmsMapping* self) MmsMapping_configureSettingGroups(MmsMapping* self)
{ {

Loading…
Cancel
Save