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:
parent
e95c50a827
commit
3159729cff
3 changed files with 69 additions and 70 deletions
|
@ -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!
|
||||
},
|
||||
{
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Add table
Reference in a new issue