From b171dfa3e06fbe050ea6391a1a955acf60495080 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 31 Aug 2014 15:25:59 +0000 Subject: [PATCH] fixed some byte ordering issues with OPAL replaced custom htonf/ntohf() functions by existing msg_swap() git-svn-id: https://zerberus.eonerc.rwth-aachen.de:8443/svn/s2ss/trunk@179 8ec27952-4edc-4aab-86aa-e87bb2611832 --- .../opal/models/send_receive/include/config.h | 2 ++ .../opal/models/send_receive/include/msg.h | 15 ++++++++++++ .../models/send_receive/include/msg_format.h | 11 +++++---- .../opal/models/send_receive/send_receive.llm | 2 ++ clients/opal/models/send_receive/src/msg.c | 22 +++++++++++++++++ clients/opal/models/send_receive/src/s2ss.c | 24 ++++++++++++------- clients/opal/models/send_receive/src/utils.c | 24 ------------------- server/include/msg_format.h | 16 ++++--------- server/src/msg.c | 13 +++++----- 9 files changed, 75 insertions(+), 54 deletions(-) create mode 100644 clients/opal/models/send_receive/include/msg.h create mode 100644 clients/opal/models/send_receive/src/msg.c delete mode 100644 clients/opal/models/send_receive/src/utils.c diff --git a/clients/opal/models/send_receive/include/config.h b/clients/opal/models/send_receive/include/config.h index d442dd210..fe1b70f8b 100644 --- a/clients/opal/models/send_receive/include/config.h +++ b/clients/opal/models/send_receive/include/config.h @@ -11,4 +11,6 @@ #define PROGNAME "S2SS" #define VERSION "0.1" +#define MAX_VALUES 16 + #endif /* _CONFIG_H_ */ diff --git a/clients/opal/models/send_receive/include/msg.h b/clients/opal/models/send_receive/include/msg.h new file mode 100644 index 000000000..060cc29ad --- /dev/null +++ b/clients/opal/models/send_receive/include/msg.h @@ -0,0 +1,15 @@ +/** Message related functions. + * + * @author Steffen Vogel + * @copyright 2014, Institute for Automation of Complex Power Systems, EONERC + */ + +#ifndef _MSG_H_ +#define _MSG_H_ + +#include "msg_format.h" + +void msg_swap(struct msg *m); + +#endif /* _MSG_H_ */ + diff --git a/clients/opal/models/send_receive/include/msg_format.h b/clients/opal/models/send_receive/include/msg_format.h index 4a04df4e3..e9676b28a 100644 --- a/clients/opal/models/send_receive/include/msg_format.h +++ b/clients/opal/models/send_receive/include/msg_format.h @@ -15,8 +15,10 @@ #include #endif +#include "config.h" + /** Maximum number of dword values in a message */ -#define MSG_VALUES 16 +#define MSG_VALUES MAX_VALUES /** The current version number for the message format */ #define MSG_VERSION 0 @@ -56,16 +58,17 @@ struct msg unsigned version: 4; /**< Specifies the format of the remaining message (see MGS_VERSION) */ unsigned type : 2; /**< Data or control message (see MSG_TYPE_*) */ unsigned endian : 1; /**< Specifies the byteorder of the message (see MSG_ENDIAN_*) */ - unsigned : 1; /**< Reserved padding bits */ + unsigned : 1; /**< Reserved padding bits */ /** Number of valid dword values in msg::data[] */ uint8_t length; /** The sequence number gets incremented by one for consecutive messages */ uint16_t sequence; + /** The message payload */ union { - float f; - uint32_t i; + float f; /**< Floating point values (note msg::endian) */ + uint32_t i; /**< Integer values (note msg::endian) */ } data[MSG_VALUES]; } __attribute__((packed)); diff --git a/clients/opal/models/send_receive/send_receive.llm b/clients/opal/models/send_receive/send_receive.llm index f5ca548ca..76b894153 100644 --- a/clients/opal/models/send_receive/send_receive.llm +++ b/clients/opal/models/send_receive/send_receive.llm @@ -40,11 +40,13 @@ INTERNAL_LIBRARY3=-lOpalAsyncApiCore s2ss.mk=Ascii include\config.h=Ascii include\interface.h=Ascii +include\msg.h=Ascii include\msg_format.h=Ascii include\sched.h=Ascii include\socket.h=Ascii src\s2ss.c=Ascii src\interface.c=Ascii +src\msg.c=Ascii src\sched.c=Ascii src\socket.c=Ascii [ExtraPutFilesComp_1_RT_LAB] diff --git a/clients/opal/models/send_receive/src/msg.c b/clients/opal/models/send_receive/src/msg.c new file mode 100644 index 000000000..a82ac2180 --- /dev/null +++ b/clients/opal/models/send_receive/src/msg.c @@ -0,0 +1,22 @@ +/** Message related functions. + * + * @author Steffen Vogel + * @copyright 2014, Institute for Automation of Complex Power Systems, EONERC + */ + +#include + +#include "msg.h" + +void msg_swap(struct msg *m) +{ + uint32_t *data = (uint32_t *) m->data; + + + /* Swap data */ + for (int i = 0; i < m->length; i++) + data[i] = bswap_32(data[i]); + + m->endian ^= 1; +} + diff --git a/clients/opal/models/send_receive/src/s2ss.c b/clients/opal/models/send_receive/src/s2ss.c index 718bcb1c3..e5439a728 100644 --- a/clients/opal/models/send_receive/src/s2ss.c +++ b/clients/opal/models/send_receive/src/s2ss.c @@ -39,7 +39,7 @@ /* This is the message format */ #include "config.h" -#include "msg_format.h" +#include "msg.h" #include "socket.h" #include "interface.h" @@ -51,10 +51,11 @@ static void *SendToIPPort(void *arg) { - unsigned SendID = 1; - unsigned i, n; + unsigned int SendID = 1; + unsigned int ModelState; + unsigned int i, n; + unsigned short seq = 0; int nbSend = 0; - unsigned ModelState; /* Data from OPAL-RT model */ double mdldata[MSG_VALUES]; @@ -97,13 +98,13 @@ static void *SendToIPPort(void *arg) /******* FORMAT TO SPECIFIC PROTOCOL HERE *****************************/ // msg.dev_id = SendID; /* Use the SendID as a device ID here */ - msg.sequence++; + msg.sequence = htons(seq++); msg.length = mdldata_size / sizeof(double); for (i = 0; i < msg.length; i++) - msg.data[i] = htonf((float) mdldata[i]); + msg.data[i] = (float) mdldata[i].f; - msg_size = 4 * (msg.length + 1); + msg_size = MSG_LEN(msg.length); /**********************************************************************/ /* Perform the actual write to the ip port */ @@ -159,6 +160,8 @@ static void *RecvFromIPPort(void *arg) msg_size = sizeof(msg); n = RecvPacket((char *) &msg, msg_size, 1.0); + /** @todo: Check and ntohs() sequence number! */ + if (msg.version != MSG_VERSION) { OpalPrint("%s: Received message with unknown version. Skipping..\n", PROGNAME); continue; @@ -169,7 +172,7 @@ static void *RecvFromIPPort(void *arg) continue; } - msg_size = 4 * (msg.length + 1); + msg_size = MSG_LEN(msg.length); /***********************************************************************/ if (n < 1) { @@ -208,8 +211,11 @@ static void *RecvFromIPPort(void *arg) PROGNAME, RecvID, mdldata_size / sizeof(double), msg.length); } + if (msg.endian != MSG_ENDIAN_HOST) + msg_swap(&msg); + for (i = 0; i < msg.length; i++) - mdldata[i] = (double) ntohf(msg.data[i]); + mdldata[i] = (double) msg.data[i].f; /************************************************************************/ OpalSetAsyncRecvIconData(mdldata, mdldata_size, RecvID); diff --git a/clients/opal/models/send_receive/src/utils.c b/clients/opal/models/send_receive/src/utils.c deleted file mode 100644 index 9e499dcab..000000000 --- a/clients/opal/models/send_receive/src/utils.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "utils.h" - -static union fi { - float f; - uint32_t i; -}; - -inline float ntohf(float flt) -{ - union fi u = { .f = flt }; - - u.i = ntohl(u.i); - - return u.f; -} - -inline float htonf(float flt) -{ - union u = { .f = flt }; - - u.i = htonl(u.i); - - return u.f; -} diff --git a/server/include/msg_format.h b/server/include/msg_format.h index 812129932..e9676b28a 100644 --- a/server/include/msg_format.h +++ b/server/include/msg_format.h @@ -38,7 +38,7 @@ #endif /** The total length of a message */ -#define MSG_LEN(values) (4 * (values + 1)) +#define MSG_LEN(values) (4 * (values + 1)) /** Initialize a message */ #define MSG_INIT(i) { \ @@ -55,17 +55,11 @@ **/ struct msg { -#if BYTE_ORDER == BIG_ENDIAN unsigned version: 4; /**< Specifies the format of the remaining message (see MGS_VERSION) */ unsigned type : 2; /**< Data or control message (see MSG_TYPE_*) */ unsigned endian : 1; /**< Specifies the byteorder of the message (see MSG_ENDIAN_*) */ - unsigned : 1; /**< Reserved padding bits */ -#else - unsigned : 1; /**< Reserved padding bits */ - unsigned endian : 1; /**< Specifies the byteorder of the message (see MSG_ENDIAN_*) */ - unsigned type : 2; /**< Data or control message (see MSG_TYPE_*) */ - unsigned version: 4; /**< Specifies the format of the remaining message (see MGS_VERSION) */ -#endif + unsigned : 1; /**< Reserved padding bits */ + /** Number of valid dword values in msg::data[] */ uint8_t length; /** The sequence number gets incremented by one for consecutive messages */ @@ -73,8 +67,8 @@ struct msg /** The message payload */ union { - float f; - uint32_t i; + float f; /**< Floating point values (note msg::endian) */ + uint32_t i; /**< Integer values (note msg::endian) */ } data[MSG_VALUES]; } __attribute__((packed)); diff --git a/server/src/msg.c b/server/src/msg.c index 002e7f7bf..23bc9513d 100644 --- a/server/src/msg.c +++ b/server/src/msg.c @@ -18,8 +18,6 @@ void msg_swap(struct msg *m) { uint32_t *data = (uint32_t *) m->data; - /* Swap sequence number */ - m->sequence = bswap_16(m->sequence); /* Swap data */ for (int i = 0; i < m->length; i++) @@ -58,19 +56,19 @@ int msg_fscan(FILE *f, struct msg *m) void msg_random(struct msg *m) { - assert(m->endian == MSG_ENDIAN_HOST); - for (int i = 0; i < m->length; i++) m->data[i].f += (float) random() / RAND_MAX - .5; + m->endian = MSG_ENDIAN_HOST; m->sequence++; } int msg_send(struct msg *m, struct node *n) { - /* We dont care about the endianess of outgoing messages */ + /* Convert headers to network byte order */ + m->sequence = ntohs(m->sequence); - if (sendto(n->sd, m, (m->length+1) * 4, 0, + if (sendto(n->sd, m, MSG_LEN(m->length), 0, (struct sockaddr *) &n->remote, sizeof(struct sockaddr_in)) < 0) perror("Failed sendto"); @@ -88,6 +86,9 @@ int msg_recv(struct msg *m, struct node *n) if (recv(n->sd, m, sizeof(struct msg), 0) < 0) perror("Failed recv"); + /* Convert headers to host byte order */ + m->sequence = htons(m->sequence); + /* Convert message to host endianess */ if (m->endian != MSG_ENDIAN_HOST) msg_swap(m);