1
0
Fork 0
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:
Steffen Vogel 2015-08-07 01:24:19 +02:00
parent b51c970368
commit 84d3e4c136
5 changed files with 93 additions and 72 deletions

View file

@ -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)

View file

@ -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

View file

@ -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_ @} */

View file

@ -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: { }
}

View file

@ -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);