1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

add new header type to socket node-type for making "fake" header in gtnet-skt mode configurable

This commit is contained in:
Steffen Vogel 2016-10-20 09:06:29 -04:00
parent e95c50a827
commit 3159729cff
3 changed files with 69 additions and 70 deletions

View file

@ -26,16 +26,24 @@ nodes = {
### The following settings are specific to the socket node-type!! ###
layer = "udp" # Layer can be one of:
# udp Send / recv UDP packets
# ip Send / recv IP packets
# eth Send / recv raw Ethernet frames (IEEE802.3)
layer = "udp", # Layer can be one of:
# udp Send / receive UDP packets
# ip Send / receive IP packets
# eth Send / receive raw Ethernet frames (IEEE802.3)
header = "gtnet-skt:fake", # Header can be one of:
# default | villas Use VILLASnode protocol (see struct msg) (default)
# none | gtnet-skt Use no header, send raw data as used by RTDS GTNETv2-SKT
# fake | gtnet-skt:fake Same as 'none', but use first three data values as
# sequence, seconds & nanoseconds timestamp
# In this mode values are uint32_t not floats!
local = "127.0.0.1:12001", # This node only received messages on this IP:Port pair
remote = "127.0.0.1:12000" # This node sents outgoing messages to this IP:Port pair
combine = 30 # Receive and sent 30 samples per message (multiplexing).
vectorize = 30 # Receive and sent 30 samples per message (combining).
},
ethernet_node = {
type = "socket", # See above.
@ -141,7 +149,7 @@ paths = (
hook = "print", # Register custom hook funktion (see src/hooks.c)
poolsize = 30 # The amount of samples which are kept in a circular buffer.
# This number must be larger than the 'combine' settings of all
# This number must be larger than the 'vectorize' settings of all
# associated input and output nodes!
},
{

View file

@ -29,8 +29,9 @@ enum socket_layer {
};
enum socket_header {
SOCKET_HEADER_DEFAULT, /**> Default header in the payload, (see msg_format.h) */
SOCKET_HEADER_GTNET_SKT /**> No header in the payload, same as HDR_NONE*/
SOCKET_HEADER_DEFAULT, /**> Default header in the payload, (see msg_format.h) */
SOCKET_HEADER_NONE, /**> No header in the payload, same as HDR_NONE*/
SOCKET_HEADER_FAKE /**> Same as SOCKET_HEADER_NONE but using the first three data values as: sequence, seconds & nano-seconds. */
};
union sockaddr_union {

View file

@ -103,8 +103,9 @@ char * socket_print(struct node *n)
}
switch (s->header) {
case SOCKET_HEADER_GTNET_SKT: header = "gtnet-skt"; break;
case SOCKET_HEADER_DEFAULT: header = "villas"; break;
case SOCKET_HEADER_NONE: header = "none"; break;
case SOCKET_HEADER_FAKE: header = "fake"; break;
case SOCKET_HEADER_DEFAULT: header = "default"; break;
}
char *local = socket_print_addr((struct sockaddr *) &s->local);
@ -214,34 +215,29 @@ int socket_read(struct node *n, struct sample *smps[], unsigned cnt)
int samples, ret, received, length;
ssize_t bytes;
if (s->header == SOCKET_HEADER_GTNET_SKT) {
if (s->header == SOCKET_HEADER_NONE || s->header == SOCKET_HEADER_FAKE) {
if (cnt < 1)
return 0;
/* The GTNETv2-SKT protocol send every sample in a single packet.
* socket_read() receives a single packet. */
int iov_len = s->header == SOCKET_HEADER_FAKE ? 2 : 1;
struct iovec iov[iov_len];
struct sample *smp = smps[0];
#if defined(GTNET_SKT_HEADER) && GTNET_SKT_HEADER
uint32_t header[3];
struct iovec iov[] = {
{ /* First three values are sequence, seconds and nano-seconds */
.iov_base = header,
.iov_len = sizeof(header)
},
#else
struct iovec iov[] = {
#endif
{ /* Remaining values are payload */
.iov_base = &smp->data,
.iov_len = SAMPLE_DATA_LEN(smp->capacity)
}
};
if (s->header == SOCKET_HEADER_FAKE) {
iov[0].iov_base = header;
iov[0].iov_len = sizeof(header);
}
/* Remaining values are payload */
iov[iov_len-1].iov_base = &smp->data;
iov[iov_len-1].iov_len = SAMPLE_DATA_LEN(smp->capacity);
struct msghdr mhdr = {
.msg_iov = iov,
.msg_iovlen = ARRAY_LEN(iov),
.msg_iovlen = iov_len,
.msg_name = (struct sockaddr *) &s->remote,
.msg_namelen = sizeof(s->remote)
};
@ -258,28 +254,23 @@ int socket_read(struct node *n, struct sample *smps[], unsigned cnt)
return -1;
}
#if defined(GTNET_SKT_HEADER) && GTNET_SKT_HEADER
length = (bytes - sizeof(header)) / SAMPLE_DATA_LEN(1);
#else
length = bytes / SAMPLE_DATA_LEN(1);
#endif
length = (s->header == SOCKET_HEADER_FAKE ? bytes - sizeof(header) : bytes) / SAMPLE_DATA_LEN(1);
if (length > smp->capacity) {
warn("Node %s received more values than supported. Dropping %u values", node_name(n), length - smp->capacity);
length = smp->capacity;
}
/** @todo Should we generate sequence no here manually?
* Or maybe optinally use the first data value as a sequence?
* However this would require the RTDS model to be changed. */
#if defined(GTNET_SKT_HEADER) && GTNET_SKT_HEADER
smp->sequence = header[0];
smp->ts.origin.tv_sec = header[1];
smp->ts.origin.tv_nsec = header[2];
#else
smp->sequence = n->sequence++;
smp->ts.origin.tv_sec = -1;
smp->ts.origin.tv_nsec = -1;
#endif
if (s->header == SOCKET_HEADER_FAKE) {
smp->sequence = header[0];
smp->ts.origin.tv_sec = header[1];
smp->ts.origin.tv_nsec = header[2];
}
else {
smp->sequence = n->sequence++; /* Fake sequence no generated by VILLASnode */
smp->ts.origin.tv_sec = -1;
smp->ts.origin.tv_nsec = -1;
}
smp->ts.received.tv_sec = -1;
smp->ts.received.tv_nsec = -1;
@ -376,35 +367,32 @@ int socket_write(struct node *n, struct sample *smps[], unsigned cnt)
int sent = 0;
/* Construct iovecs */
if (s->header == SOCKET_HEADER_GTNET_SKT) {
if (s->header == SOCKET_HEADER_NONE || s->header == SOCKET_HEADER_FAKE) {
if (cnt < 1)
return 0;
for (int i = 0; i < cnt; i++) {
#if defined(GTNET_SKT_HEADER) && GTNET_SKT_HEADER
uint32_t header[] = {
smps[i]->sequence,
smps[i]->ts.origin.tv_sec,
smps[i]->ts.origin.tv_nsec
};
for (int i = 0; i < cnt; i++) {
int iov_len = s->header == SOCKET_HEADER_FAKE ? 2 : 1;
struct iovec iov[iov_len];
struct iovec iov[] = {
{ /* First three values are sequence, seconds and nano-seconds */
.iov_base = header,
.iov_len = sizeof(header)
},
#else
struct iovec iov[] = {
#endif
{ /* Remaining values are payload */
.iov_base = &smps[i]->data,
.iov_len = SAMPLE_DATA_LEN(smps[i]->length)
}
};
/* First three values are sequence, seconds and nano-seconds timestamps */
uint32_t header[3];
if (s->header == SOCKET_HEADER_FAKE) {
header[0] = smps[i]->sequence;
header[1] = smps[i]->ts.origin.tv_sec;
header[2] = smps[i]->ts.origin.tv_nsec;
iov[0].iov_base = header;
iov[0].iov_len = sizeof(header);
}
/* Remaining values are payload */
iov[iov_len-1].iov_base = &smps[i]->data;
iov[iov_len-1].iov_len = SAMPLE_DATA_LEN(smps[i]->length);
struct msghdr mhdr = {
.msg_iov = iov,
.msg_iovlen = ARRAY_LEN(iov),
.msg_iovlen = iov_len,
.msg_name = (struct sockaddr *) &s->remote,
.msg_namelen = sizeof(s->remote)
};
@ -480,9 +468,11 @@ int socket_parse(struct node *n, config_setting_t *cfg)
if (!config_setting_lookup_string(cfg, "header", &hdr))
s->header = SOCKET_HEADER_DEFAULT;
else {
if (!strcmp(hdr, "gtnet-skt") || (!strcmp(hdr, "none")))
s->header = SOCKET_HEADER_GTNET_SKT;
else if (!strcmp(hdr, "default") || !strcmp(hdr, "villas"))
if (!strcmp(hdr, "gtnet-skt") || (!strcmp(hdr, "none")))
s->header = SOCKET_HEADER_NONE;
else if (!strcmp(hdr, "gtnet-skt:fake") || (!strcmp(hdr, "fake")))
s->header = SOCKET_HEADER_FAKE;
else if (!strcmp(hdr, "villas") || !strcmp(hdr, "default"))
s->header = SOCKET_HEADER_DEFAULT;
else
cerror(cfg, "Invalid application header type '%s' for node %s", hdr, node_name(n));