mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
removed last pieces of TCP support and pseudo node-types: "udp", "ieee802.3" and "ip"
The node-types have been replaced by the new type "socket" which features a setting called "layer" to choose between "udp", "ip" and "eth"
This commit is contained in:
parent
b51c970368
commit
84d3e4c136
5 changed files with 93 additions and 72 deletions
|
@ -32,30 +32,37 @@ stats = 3; # The interval in seconds to print path statistics.
|
|||
|
||||
nodes = {
|
||||
udp_node = { # The dictionary is indexed by the name of the node.
|
||||
type = "udp", # Type can be one of:
|
||||
type = "socket", # Type can be one of:
|
||||
# socket
|
||||
# opal
|
||||
# file
|
||||
# gtfpga
|
||||
|
||||
### The following settings are specific to the socket node-type!! ###
|
||||
layer = "udp" # Layer can be one of:
|
||||
# udp Send / recv UDP packets
|
||||
# tcp Send / recv TCP packets
|
||||
# ip Send / recv IP packets
|
||||
# ieee802.3 Send / recv raw Ethernet frames
|
||||
# opal Read / write via libOpalAsyncApi
|
||||
# gtfpga Read / write to memory mapped PCIe card
|
||||
# eth Send / recv raw Ethernet frames (IEEE802.3)
|
||||
|
||||
|
||||
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).
|
||||
},
|
||||
tcp_node = {
|
||||
type = "tcp", # See above.
|
||||
ethernet_node = {
|
||||
type = "socket", # See above.
|
||||
|
||||
### The following settings are specific to the socket node-type!! ###
|
||||
layer = "eth",
|
||||
local = "*:12002", # It's possible to use an '*' for both the port and address
|
||||
# in UDP / TCP and IP modes.
|
||||
# This will choose a random port.
|
||||
# And listen on all available interfaces.
|
||||
remote = "127.0.0.1:12003", # Currently IPv6 is not supported!
|
||||
remote = "12:34:56:78:90:12003", # Currently IPv6 is not supported!
|
||||
|
||||
netem = { # Network emulation settings
|
||||
# Those settings can be specified for each node invidually!
|
||||
|
||||
delay = 100000, # Additional latency in microseconds
|
||||
jitter = 30000, # Jitter in uS
|
||||
distribution = "normal", # Distribution of delay: uniform, normal, pareto, paretonormal
|
||||
|
@ -66,12 +73,16 @@ nodes = {
|
|||
},
|
||||
opal_node = { # The server can be started as an Asynchronous process
|
||||
type = "opal", # from within an OPAL-RT model.
|
||||
|
||||
### The following settings are specific to the opal node-type!! ###
|
||||
send_id = 1, # It's possible to have multiple send / recv Icons per model
|
||||
recv_id = 1, # Specify the ID here.
|
||||
reply = true
|
||||
},
|
||||
file_node = {
|
||||
type = "file",
|
||||
|
||||
### The following settings are specific to the file node-type!! ###
|
||||
mode = "w+", # The mode in which files should be opened (see open(2))
|
||||
# You might want to use "a+" to append to a file
|
||||
|
||||
|
@ -87,6 +98,8 @@ nodes = {
|
|||
},
|
||||
gtfpga_node = {
|
||||
type = "gtfpga",
|
||||
|
||||
### The following settings are specific to the gtfpga node-type!! ###
|
||||
slot = "01:00.0", # The PCIe slot location (see first column in 'lspci' output)
|
||||
id = "1ab8:4005", # The PCIe vendor:device ID (see third column in 'lspci -n' output)
|
||||
|
||||
|
|
|
@ -41,16 +41,10 @@
|
|||
|
||||
/** Node type: layer, protocol, listen/connect */
|
||||
enum node_type {
|
||||
BSD_SOCKET, /**< BSD Socket API */
|
||||
LOG_FILE, /**< File IO */
|
||||
OPAL_ASYNC, /**< OPAL-RT Asynchronous Process Api */
|
||||
GTFPGA, /**< Xilinx ML507 GTFPGA card */
|
||||
IEEE_802_3 = 0x10, /**< BSD socket: AF_PACKET SOCK_DGRAM */
|
||||
IP, /**< BSD socket: AF_INET SOCK_RAW */
|
||||
UDP, /**< BSD socket: AF_INET SOCK_DGRAM */
|
||||
TCPD, /**< BSD socket: AF_INET SOCK_STREAM bind + listen + accept */
|
||||
TCP, /**< BSD socket: AF_INET SOCK_STREAM bind + connect */
|
||||
|
||||
SOCKET = 0xF0 /**< Mask for BSD socket types */
|
||||
GTFPGA /**< Xilinx ML507 GTFPGA card */
|
||||
};
|
||||
|
||||
/** C++ like vtable construct for node_types
|
||||
|
|
|
@ -19,14 +19,21 @@
|
|||
|
||||
#include "node.h"
|
||||
|
||||
enum socket_layer {
|
||||
LAYER_ETH,
|
||||
LAYER_IP,
|
||||
LAYER_UDP
|
||||
};
|
||||
|
||||
struct socket {
|
||||
/** The socket descriptor */
|
||||
int sd;
|
||||
/** The socket descriptor for an established TCP connection */
|
||||
int sd2;
|
||||
/** Socket mark for netem, routing and filtering */
|
||||
int mark;
|
||||
|
||||
/** The OSI / IP layer which should be used for this socket */
|
||||
enum socket_layer layer;
|
||||
|
||||
/** Local address of the socket */
|
||||
struct sockaddr_storage local;
|
||||
/** Remote address of the socket */
|
||||
|
@ -85,11 +92,11 @@ int socket_print_addr(char *buf, int len, struct sockaddr *sa);
|
|||
*
|
||||
* @param str A string specifiying the socket address. See description for allowed formats.
|
||||
* @param sa A pointer to the resolved address
|
||||
* @param type Specifies the address type in which the addr is given
|
||||
* @param layer Specifies the address type in which the addr is given
|
||||
* @param flags Flags for getaddrinfo(2)
|
||||
* @retval 0 Success. Everything went well.
|
||||
* @retval <0 Error. Something went wrong.
|
||||
*/
|
||||
int socket_parse_addr(const char *str, struct sockaddr *sa, enum node_type type, int flags);
|
||||
int socket_parse_addr(const char *str, struct sockaddr *sa, enum socket_layer layer, int flags);
|
||||
|
||||
#endif /** _SOCKET_H_ @} */
|
||||
|
|
|
@ -36,10 +36,8 @@ struct node_vtable vtables[] = {
|
|||
#ifdef ENABLE_GTFPGA
|
||||
VTABLE(GTFPGA, "gtfpga", gtfpga),
|
||||
#endif
|
||||
VTABLE(LOG_FILE, "file", file),
|
||||
VTABLE(IEEE_802_3, "ieee802.3", socket),
|
||||
VTABLE(IP, "ip", socket),
|
||||
VTABLE(UDP, "udp", socket)
|
||||
VTABLE(BSD_SOCKET, "socket", socket),
|
||||
VTABLE(LOG_FILE, "file", file)
|
||||
};
|
||||
|
||||
int node_init(int argc, char *argv[], struct settings *set)
|
||||
|
@ -120,9 +118,7 @@ int node_stop(struct node *n)
|
|||
void node_reverse(struct node *n)
|
||||
{
|
||||
switch (n->vt->type) {
|
||||
case IEEE_802_3:
|
||||
case IP:
|
||||
case UDP:
|
||||
case BSD_SOCKET:
|
||||
SWAP(n->socket->remote, n->socket->local);
|
||||
break;
|
||||
default: { }
|
||||
|
@ -137,10 +133,9 @@ struct node * node_create()
|
|||
void node_destroy(struct node *n)
|
||||
{
|
||||
switch (n->vt->type) {
|
||||
case IEEE_802_3:
|
||||
case IP:
|
||||
case UDP:
|
||||
case BSD_SOCKET:
|
||||
free(n->socket->netem);
|
||||
break;
|
||||
default: { }
|
||||
}
|
||||
|
||||
|
|
|
@ -98,10 +98,10 @@ int socket_open(struct node *n)
|
|||
int ret;
|
||||
|
||||
/* Create socket */
|
||||
switch (node_type(n)) {
|
||||
case UDP: s->sd = socket(sin->sin_family, SOCK_DGRAM, IPPROTO_UDP); break;
|
||||
case IP: s->sd = socket(sin->sin_family, SOCK_RAW, ntohs(sin->sin_port)); break;
|
||||
case IEEE_802_3:s->sd = socket(sll->sll_family, SOCK_DGRAM, sll->sll_protocol); break;
|
||||
switch (s->layer) {
|
||||
case LAYER_UDP: s->sd = socket(sin->sin_family, SOCK_DGRAM, IPPROTO_UDP); break;
|
||||
case LAYER_IP: s->sd = socket(sin->sin_family, SOCK_RAW, ntohs(sin->sin_port)); break;
|
||||
case LAYER_ETH: s->sd = socket(sll->sll_family, SOCK_DGRAM, sll->sll_protocol); break;
|
||||
default:
|
||||
error("Invalid socket type!");
|
||||
}
|
||||
|
@ -122,9 +122,9 @@ int socket_open(struct node *n)
|
|||
|
||||
/* Set socket priority, QoS or TOS IP options */
|
||||
int prio;
|
||||
switch (node_type(n)) {
|
||||
case UDP:
|
||||
case IP:
|
||||
switch (s->layer) {
|
||||
case LAYER_UDP:
|
||||
case LAYER_IP:
|
||||
prio = IPTOS_LOWDELAY;
|
||||
if (setsockopt(s->sd, IPPROTO_IP, IP_TOS, &prio, sizeof(prio)))
|
||||
serror("Failed to set type of service (QoS)");
|
||||
|
@ -150,10 +150,7 @@ int socket_close(struct node *n)
|
|||
|
||||
if (s->sd >= 0)
|
||||
close(s->sd);
|
||||
|
||||
if (s->sd2 >= 0)
|
||||
close(s->sd2);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -216,62 +213,77 @@ int socket_read(struct node *n, struct msg *pool, int poolsize, int first, int c
|
|||
int socket_write(struct node *n, struct msg *pool, int poolsize, int first, int cnt)
|
||||
{
|
||||
struct socket *s = n->socket;
|
||||
int ret = -1;
|
||||
|
||||
int ret = -1, sent = 0;
|
||||
|
||||
struct iovec iov[cnt];
|
||||
struct msghdr mhdr = {
|
||||
.msg_iov = iov,
|
||||
.msg_iovlen = ARRAY_LEN(iov)
|
||||
};
|
||||
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
struct msg *n = &pool[(first+poolsize+i) % poolsize];
|
||||
|
||||
/* Convert headers to host byte order */
|
||||
struct msg *n = &pool[(first+i) % poolsize];
|
||||
|
||||
if (n->type == MSG_TYPE_EMPTY)
|
||||
continue;
|
||||
|
||||
/* Convert headers to network byte order */
|
||||
n->sequence = htons(n->sequence);
|
||||
|
||||
iov[i].iov_base = n;
|
||||
iov[i].iov_len = MSG_LEN(n);
|
||||
|
||||
iov[sent].iov_base = n;
|
||||
iov[sent].iov_len = MSG_LEN(n);
|
||||
|
||||
sent++;
|
||||
}
|
||||
|
||||
struct msghdr mhdr = {
|
||||
.msg_iov = iov,
|
||||
.msg_iovlen = sent
|
||||
};
|
||||
|
||||
/* Specify destination address for connection-less procotols */
|
||||
switch (node_type(n)) {
|
||||
case IEEE_802_3:
|
||||
case IP:
|
||||
case UDP:
|
||||
switch (s->layer) {
|
||||
case LAYER_UDP:
|
||||
case LAYER_IP:
|
||||
case LAYER_ETH:
|
||||
mhdr.msg_name = (struct sockaddr *) &s->remote;
|
||||
mhdr.msg_namelen = sizeof(s->remote);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = sendmsg(s->sd, &mhdr, 0);
|
||||
if (ret < 0)
|
||||
serror("Failed send");
|
||||
|
||||
return cnt;
|
||||
return sent;
|
||||
}
|
||||
|
||||
int socket_parse(config_setting_t *cfg, struct node *n)
|
||||
{
|
||||
const char *local, *remote;
|
||||
const char *local, *remote, *layer;
|
||||
int ret;
|
||||
|
||||
struct socket *s = alloc(sizeof(struct socket));
|
||||
|
||||
if (!config_setting_lookup_string(cfg, "layer", &layer))
|
||||
cerror(cfg, "Missing layer setting for node '%s'", n->name);
|
||||
|
||||
if (!strcmp(layer, "eth"))
|
||||
s->layer = LAYER_ETH;
|
||||
else if (!strcmp(layer, "ip"))
|
||||
s->layer = LAYER_IP;
|
||||
else if (!strcmp(layer, "udp"))
|
||||
s->layer = LAYER_UDP;
|
||||
else
|
||||
cerror(cfg, "Invalid layer '%s' for node '%s'", layer, n->name);
|
||||
|
||||
if (!config_setting_lookup_string(cfg, "remote", &remote))
|
||||
cerror(cfg, "Missing remote address for node '%s'", n->name);
|
||||
|
||||
if (!config_setting_lookup_string(cfg, "local", &local))
|
||||
cerror(cfg, "Missing local address for node '%s'", n->name);
|
||||
|
||||
ret = socket_parse_addr(local, (struct sockaddr *) &s->local, node_type(n), AI_PASSIVE);
|
||||
ret = socket_parse_addr(local, (struct sockaddr *) &s->local, s->layer, AI_PASSIVE);
|
||||
if (ret)
|
||||
cerror(cfg, "Failed to resolve local address '%s' of node '%s': %s",
|
||||
local, n->name, gai_strerror(ret));
|
||||
|
||||
ret = socket_parse_addr(remote, (struct sockaddr *) &s->remote, node_type(n), 0);
|
||||
ret = socket_parse_addr(remote, (struct sockaddr *) &s->remote, s->layer, 0);
|
||||
if (ret)
|
||||
cerror(cfg, "Failed to resolve remote address '%s' of node '%s': %s",
|
||||
remote, n->name, gai_strerror(ret));
|
||||
|
@ -317,7 +329,7 @@ int socket_print_addr(char *buf, int len, struct sockaddr *sa)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int socket_parse_addr(const char *addr, struct sockaddr *sa, enum node_type type, int flags)
|
||||
int socket_parse_addr(const char *addr, struct sockaddr *sa, enum socket_layer layer, int flags)
|
||||
{
|
||||
/** @todo: Add support for IPv6 */
|
||||
|
||||
|
@ -362,14 +374,14 @@ int socket_parse_addr(const char *addr, struct sockaddr *sa, enum node_type type
|
|||
if (service && !strcmp(service, "*"))
|
||||
service = NULL;
|
||||
|
||||
switch (type) {
|
||||
case IP:
|
||||
switch (layer) {
|
||||
case LAYER_IP:
|
||||
hint.ai_socktype = SOCK_RAW;
|
||||
hint.ai_protocol = (service) ? strtol(service, NULL, 0) : IPPROTO_S2SS;
|
||||
hint.ai_flags |= AI_NUMERICSERV;
|
||||
break;
|
||||
|
||||
case UDP:
|
||||
case LAYER_UDP:
|
||||
hint.ai_socktype = SOCK_DGRAM;
|
||||
hint.ai_protocol = IPPROTO_UDP;
|
||||
break;
|
||||
|
@ -380,10 +392,10 @@ int socket_parse_addr(const char *addr, struct sockaddr *sa, enum node_type type
|
|||
|
||||
/* Lookup address */
|
||||
struct addrinfo *result;
|
||||
ret = getaddrinfo(node, (type == IP) ? NULL : service, &hint, &result);
|
||||
ret = getaddrinfo(node, (layer == LAYER_IP) ? NULL : service, &hint, &result);
|
||||
if (!ret) {
|
||||
|
||||
if (type == IP) {
|
||||
|
||||
if (layer == LAYER_IP) {
|
||||
/* We mis-use the sin_port field to store the IP protocol number on RAW sockets */
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *) result->ai_addr;
|
||||
sin->sin_port = htons(result->ai_protocol);
|
||||
|
|
Loading…
Add table
Reference in a new issue