- GOOSE: option to enable/disable VLAN tagging

- IED Server: Allow setting different interfaces for different GOOSE publishers
pull/179/head
Michael Zillgith 6 years ago
parent 46d7f6ff2d
commit 6b2404e80b

@ -59,9 +59,21 @@ int main(int argc, char** argv) {
char* ethernetIfcID = argv[1]; char* ethernetIfcID = argv[1];
printf("Using GOOSE interface: %s\n", ethernetIfcID); printf("Using GOOSE interface: %s\n", ethernetIfcID);
/* set GOOSE interface for all GOOSE publishers (GCBs) */
IedServer_setGooseInterfaceId(iedServer, ethernetIfcID); IedServer_setGooseInterfaceId(iedServer, ethernetIfcID);
} }
if (argc > 2) {
char* ethernetIfcID = argv[2];
printf("Using GOOSE interface for GenericIO/LLN0.gcbAnalogValues: %s\n", ethernetIfcID);
/* set GOOSE interface for a particular GOOSE publisher (GCB) */
IedServer_setGooseInterfaceIdEx(iedServer, IEDMODEL_GenericIO_LLN0, "gcbAnalogValues", ethernetIfcID);
}
/* MMS server will be instructed to start listening to client connections. */ /* MMS server will be instructed to start listening to client connections. */
IedServer_start(iedServer, 102); IedServer_start(iedServer, 102);

@ -36,7 +36,7 @@
#define GOOSE_MAX_MESSAGE_SIZE 1518 #define GOOSE_MAX_MESSAGE_SIZE 1518
static void static void
prepareGooseBuffer(GoosePublisher self, CommParameters* parameters, const char* interfaceID); prepareGooseBuffer(GoosePublisher self, CommParameters* parameters, const char* interfaceID, bool useVlanTags);
struct sGoosePublisher { struct sGoosePublisher {
uint8_t* buffer; uint8_t* buffer;
@ -63,13 +63,12 @@ struct sGoosePublisher {
MmsValue* timestamp; /* time when stNum is increased */ MmsValue* timestamp; /* time when stNum is increased */
}; };
GoosePublisher GoosePublisher
GoosePublisher_create(CommParameters* parameters, const char* interfaceID) GoosePublisher_createEx(CommParameters* parameters, const char* interfaceID, bool useVlanTag)
{ {
GoosePublisher self = (GoosePublisher) GLOBAL_CALLOC(1, sizeof(struct sGoosePublisher)); GoosePublisher self = (GoosePublisher) GLOBAL_CALLOC(1, sizeof(struct sGoosePublisher));
prepareGooseBuffer(self, parameters, interfaceID); prepareGooseBuffer(self, parameters, interfaceID, useVlanTag);
self->timestamp = MmsValue_newUtcTimeByMsTime(Hal_getTimeInMs()); self->timestamp = MmsValue_newUtcTimeByMsTime(Hal_getTimeInMs());
@ -78,6 +77,12 @@ GoosePublisher_create(CommParameters* parameters, const char* interfaceID)
return self; return self;
} }
GoosePublisher
GoosePublisher_create(CommParameters* parameters, const char* interfaceID)
{
return GoosePublisher_createEx(parameters, interfaceID, true);
}
void void
GoosePublisher_destroy(GoosePublisher self) GoosePublisher_destroy(GoosePublisher self)
{ {
@ -160,7 +165,7 @@ GoosePublisher_setTimeAllowedToLive(GoosePublisher self, uint32_t timeAllowedToL
} }
static void static void
prepareGooseBuffer(GoosePublisher self, CommParameters* parameters, const char* interfaceID) prepareGooseBuffer(GoosePublisher self, CommParameters* parameters, const char* interfaceID, bool useVlanTags)
{ {
uint8_t srcAddr[6]; uint8_t srcAddr[6];
@ -201,19 +206,19 @@ prepareGooseBuffer(GoosePublisher self, CommParameters* parameters, const char*
int bufPos = 12; int bufPos = 12;
#if 1 if (useVlanTags) {
/* Priority tag - IEEE 802.1Q */ /* Priority tag - IEEE 802.1Q */
self->buffer[bufPos++] = 0x81; self->buffer[bufPos++] = 0x81;
self->buffer[bufPos++] = 0x00; self->buffer[bufPos++] = 0x00;
uint8_t tci1 = priority << 5; uint8_t tci1 = priority << 5;
tci1 += vlanId / 256; tci1 += vlanId / 256;
uint8_t tci2 = vlanId % 256; uint8_t tci2 = vlanId % 256;
self->buffer[bufPos++] = tci1; /* Priority + VLAN-ID */ self->buffer[bufPos++] = tci1; /* Priority + VLAN-ID */
self->buffer[bufPos++] = tci2; /* VLAN-ID */ self->buffer[bufPos++] = tci2; /* VLAN-ID */
#endif }
/* EtherType GOOSE */ /* EtherType GOOSE */
self->buffer[bufPos++] = 0x88; self->buffer[bufPos++] = 0x88;

@ -49,6 +49,9 @@ typedef struct sGoosePublisher* GoosePublisher;
LIB61850_API GoosePublisher LIB61850_API GoosePublisher
GoosePublisher_create(CommParameters* parameters, const char* interfaceID); GoosePublisher_create(CommParameters* parameters, const char* interfaceID);
LIB61850_API GoosePublisher
GoosePublisher_createEx(CommParameters* parameters, const char* interfaceID, bool useVlanTag);
LIB61850_API void LIB61850_API void
GoosePublisher_destroy(GoosePublisher self); GoosePublisher_destroy(GoosePublisher self);

@ -459,6 +459,8 @@ IedServer_getMmsServer(IedServer self);
* then configured GOOSE control blocks keep inactive until a MMS client enables * then configured GOOSE control blocks keep inactive until a MMS client enables
* them by writing to the GOOSE control block. * them by writing to the GOOSE control block.
* *
* Note: This function has no effect when CONFIG_INCLUDE_GOOSE_SUPPORT is not set.
*
* \param self the instance of IedServer to operate on. * \param self the instance of IedServer to operate on.
*/ */
LIB61850_API void LIB61850_API void
@ -470,6 +472,8 @@ IedServer_enableGoosePublishing(IedServer self);
* This will set the GoEna attribute of all configured GOOSE control blocks * This will set the GoEna attribute of all configured GOOSE control blocks
* to false. This will stop GOOSE transmission. * to false. This will stop GOOSE transmission.
* *
* Note: This function has no effect when CONFIG_INCLUDE_GOOSE_SUPPORT is not set.
*
* \param self the instance of IedServer to operate on. * \param self the instance of IedServer to operate on.
*/ */
LIB61850_API void LIB61850_API void
@ -482,12 +486,46 @@ IedServer_disableGoosePublishing(IedServer self);
* default interface ID from stack_config.h is used. Note the interface ID is operating system * default interface ID from stack_config.h is used. Note the interface ID is operating system
* specific! * specific!
* *
* Note: This function has no effect when CONFIG_INCLUDE_GOOSE_SUPPORT is not set.
*
* \param self the instance of IedServer to operate on. * \param self the instance of IedServer to operate on.
* \param interfaceId the ID of the ethernet interface to be used for GOOSE publishing * \param interfaceId the ID of the ethernet interface to be used for GOOSE publishing
*/ */
LIB61850_API void LIB61850_API void
IedServer_setGooseInterfaceId(IedServer self, const char* interfaceId); IedServer_setGooseInterfaceId(IedServer self, const char* interfaceId);
/**
* \brief Set the Ethernet interface to be used by GOOSE publishing
*
* This function can be used to set the GOOSE interface ID forG all CBs (parameter ln = NULL) or for
* a specific GCB specified by the logical node instance and the GCB name.
*
* Note: This function has no effect when CONFIG_INCLUDE_GOOSE_SUPPORT is not set.
*
* \param self the instance of IedServer to operate on.
* \param ln the logical node that contains the GCB or NULL to enable/disable VLAN tagging for all GCBs
* \param gcbName the name (not object reference!) of the GCB
* \param interfaceId the ID of the ethernet interface to be used for GOOSE publishing
*/
LIB61850_API void
IedServer_setGooseInterfaceIdEx(IedServer self, LogicalNode* ln, const char* gcbName, const char* interfaceId);
/**
* \brief Enable/disable the use of VLAN tags in GOOSE messages
*
* This function can be used to enable/disable VLAN tagging for all GCBs (parameter ln = NULL) or for
* a specific GCB specified by the logical node instance and the GCB name.
*
* Note: This function has no effect when CONFIG_INCLUDE_GOOSE_SUPPORT is not set.
*
* \param self the instance of IedServer to operate on
* \param ln the logical node that contains the GCB or NULL to enable/disable VLAN tagging for all GCBs
* \param gcbName the name (not object reference!) of the GCB
* \param useVlanTag true to enable VLAN tagging, false otherwise
*/
LIB61850_API void
IedServer_useGooseVlanTag(IedServer self, LogicalNode* ln, const char* gcbName, bool useVlanTag);
/**@}*/ /**@}*/
/** /**

@ -1,7 +1,7 @@
/* /*
* mms_goose.h * mms_goose.h
* *
* Copyright 2013-2018 Michael Zillgith * Copyright 2013-2019 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -35,6 +35,15 @@ MmsGooseControlBlock_destroy(MmsGooseControlBlock self);
LIB61850_INTERNAL MmsDomain* LIB61850_INTERNAL MmsDomain*
MmsGooseControlBlock_getDomain(MmsGooseControlBlock self); MmsGooseControlBlock_getDomain(MmsGooseControlBlock self);
LIB61850_INTERNAL void
MmsGooseControlBlock_useGooseVlanTag(MmsGooseControlBlock self, bool useVlanTag);
LIB61850_INTERNAL void
MmsGooseControlBlock_setGooseInterfaceId(MmsGooseControlBlock self, const char* interfaceId);
LIB61850_INTERNAL LogicalNode*
MmsGooseControlBlock_getLogicalNode(MmsGooseControlBlock self);
LIB61850_INTERNAL char* LIB61850_INTERNAL char*
MmsGooseControlBlock_getLogicalNodeName(MmsGooseControlBlock self); MmsGooseControlBlock_getLogicalNodeName(MmsGooseControlBlock self);

@ -106,6 +106,12 @@ MmsMapping_enableGoosePublishing(MmsMapping* self);
LIB61850_INTERNAL void LIB61850_INTERNAL void
MmsMapping_disableGoosePublishing(MmsMapping* self); MmsMapping_disableGoosePublishing(MmsMapping* self);
LIB61850_INTERNAL void
MmsMapping_useGooseVlanTag(MmsMapping* self, LogicalNode* ln, const char* gcbName, bool useVlanTag);
LIB61850_INTERNAL void
MmsMapping_setGooseInterfaceId(MmsMapping* self, LogicalNode* ln, const char* gcbName, const char* interfaceId);
LIB61850_INTERNAL void LIB61850_INTERNAL void
MmsMapping_addControlObject(MmsMapping* self, ControlObject* controlObject); MmsMapping_addControlObject(MmsMapping* self, ControlObject* controlObject);

@ -1287,6 +1287,21 @@ IedServer_updateQuality(IedServer self, DataAttribute* dataAttribute, Quality qu
} }
void
IedServer_useGooseVlanTag(IedServer self, LogicalNode* ln, const char* gcbName, bool useVlanTag)
{
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
MmsMapping_useGooseVlanTag(self->mmsMapping, ln, gcbName, useVlanTag);
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
}
void
IedServer_setGooseInterfaceIdEx(IedServer self, LogicalNode* ln, const char* gcbName, const char* interfaceId)
{
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
MmsMapping_setGooseInterfaceId(self->mmsMapping, ln, gcbName, interfaceId);
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
}
void void
IedServer_enableGoosePublishing(IedServer self) IedServer_enableGoosePublishing(IedServer self)

@ -39,7 +39,9 @@
struct sMmsGooseControlBlock { struct sMmsGooseControlBlock {
char* name; char* name;
bool goEna; int goEna:1;
int isDynamicDataSet:1;
int useVlanTag:1;
char* dstAddress; char* dstAddress;
@ -50,7 +52,6 @@ struct sMmsGooseControlBlock {
GoosePublisher publisher; GoosePublisher publisher;
DataSet* dataSet; DataSet* dataSet;
bool isDynamicDataSet;
LinkedList dataSetValues; LinkedList dataSetValues;
uint64_t nextPublishTime; uint64_t nextPublishTime;
@ -68,6 +69,8 @@ struct sMmsGooseControlBlock {
char* goCBRef; char* goCBRef;
char* goId; char* goId;
char* dataSetRef; char* dataSetRef;
char* gooseInterfaceId;
}; };
MmsGooseControlBlock MmsGooseControlBlock
@ -75,9 +78,12 @@ MmsGooseControlBlock_create()
{ {
MmsGooseControlBlock self = (MmsGooseControlBlock) GLOBAL_CALLOC(1, sizeof(struct sMmsGooseControlBlock)); MmsGooseControlBlock self = (MmsGooseControlBlock) GLOBAL_CALLOC(1, sizeof(struct sMmsGooseControlBlock));
if (self) {
self->useVlanTag = true;
#if (CONFIG_MMS_THREADLESS_STACK != 1) #if (CONFIG_MMS_THREADLESS_STACK != 1)
self->publisherMutex = Semaphore_create(1); self->publisherMutex = Semaphore_create(1);
#endif #endif
}
return self; return self;
} }
@ -112,11 +118,29 @@ MmsGooseControlBlock_destroy(MmsGooseControlBlock self)
} }
} }
if (self->gooseInterfaceId != NULL)
GLOBAL_FREEMEM(self->gooseInterfaceId);
MmsValue_delete(self->mmsValue); MmsValue_delete(self->mmsValue);
GLOBAL_FREEMEM(self); GLOBAL_FREEMEM(self);
} }
void
MmsGooseControlBlock_useGooseVlanTag(MmsGooseControlBlock self, bool useVlanTag)
{
self->useVlanTag = useVlanTag;
}
void
MmsGooseControlBlock_setGooseInterfaceId(MmsGooseControlBlock self, const char* interfaceId)
{
if (self->gooseInterfaceId != NULL)
GLOBAL_FREEMEM(self->gooseInterfaceId);
self->gooseInterfaceId = StringUtils_copyString(interfaceId);
}
MmsDomain* MmsDomain*
MmsGooseControlBlock_getDomain(MmsGooseControlBlock self) MmsGooseControlBlock_getDomain(MmsGooseControlBlock self)
{ {
@ -129,6 +153,12 @@ MmsGooseControlBlock_getDataSet(MmsGooseControlBlock self)
return self->dataSet; return self->dataSet;
} }
LogicalNode*
MmsGooseControlBlock_getLogicalNode(MmsGooseControlBlock self)
{
return self->logicalNode;
}
char* char*
MmsGooseControlBlock_getLogicalNodeName(MmsGooseControlBlock self) MmsGooseControlBlock_getLogicalNodeName(MmsGooseControlBlock self)
{ {
@ -222,7 +252,10 @@ MmsGooseControlBlock_enable(MmsGooseControlBlock self)
memcpy(commParameters.dstAddress, MmsValue_getOctetStringBuffer(macAddress), 6); memcpy(commParameters.dstAddress, MmsValue_getOctetStringBuffer(macAddress), 6);
self->publisher = GoosePublisher_create(&commParameters, self->mmsMapping->gooseInterfaceId); if (self->gooseInterfaceId)
self->publisher = GoosePublisher_createEx(&commParameters, self->gooseInterfaceId, self->useVlanTag);
else
self->publisher = GoosePublisher_createEx(&commParameters, self->mmsMapping->gooseInterfaceId, self->useVlanTag);
self->minTime = MmsValue_toUint32(MmsValue_getElement(self->mmsValue, 6)); self->minTime = MmsValue_toUint32(MmsValue_getElement(self->mmsValue, 6));
self->maxTime = MmsValue_toUint32(MmsValue_getElement(self->mmsValue, 7)); self->maxTime = MmsValue_toUint32(MmsValue_getElement(self->mmsValue, 7));

@ -2914,6 +2914,44 @@ MmsMapping_enableGoosePublishing(MmsMapping* self)
} }
void
MmsMapping_useGooseVlanTag(MmsMapping* self, LogicalNode* ln, const char* gcbName, bool useVlanTag)
{
LinkedList element = self->gseControls;
while ((element = LinkedList_getNext(element)) != NULL) {
MmsGooseControlBlock gcb = (MmsGooseControlBlock) element->data;
if (ln == NULL) {
MmsGooseControlBlock_useGooseVlanTag(gcb, useVlanTag);
}
else {
if ((MmsGooseControlBlock_getLogicalNode(gcb) == ln) && !strcmp(MmsGooseControlBlock_getName(gcb), gcbName)) {
MmsGooseControlBlock_useGooseVlanTag(gcb, useVlanTag);
}
}
}
}
void
MmsMapping_setGooseInterfaceId(MmsMapping* self, LogicalNode* ln, const char* gcbName, const char* interfaceId)
{
LinkedList element = self->gseControls;
while ((element = LinkedList_getNext(element)) != NULL) {
MmsGooseControlBlock gcb = (MmsGooseControlBlock) element->data;
if (ln == NULL) {
MmsGooseControlBlock_setGooseInterfaceId(gcb, interfaceId);
}
else {
if ((MmsGooseControlBlock_getLogicalNode(gcb) == ln) && !strcmp(MmsGooseControlBlock_getName(gcb), gcbName)) {
MmsGooseControlBlock_setGooseInterfaceId(gcb, interfaceId);
}
}
}
}
void void
MmsMapping_disableGoosePublishing(MmsMapping* self) MmsMapping_disableGoosePublishing(MmsMapping* self)
{ {

Loading…
Cancel
Save