From 4745a799fff59597ccf849996b40dfa5c97913c7 Mon Sep 17 00:00:00 2001
From: Umar Farooq <ufarooq@eonerc.rwth-aachen.de>
Date: Thu, 27 Oct 2016 19:25:29 +0200
Subject: [PATCH] Add endianness setting in config file to nodes

---
 etc/gtnet-skt/test5.conf |  1 +
 include/villas/node.h    |  2 ++
 include/villas/sample.h  | 10 ++++++++++
 lib/cfg.c                | 13 ++++++++++++-
 lib/nodes/socket.c       |  1 +
 lib/sample.c             | 10 ++++++++--
 6 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/etc/gtnet-skt/test5.conf b/etc/gtnet-skt/test5.conf
index 582cf6604..a8d9ce9d9 100644
--- a/etc/gtnet-skt/test5.conf
+++ b/etc/gtnet-skt/test5.conf
@@ -35,6 +35,7 @@ nodes = {
 		local = "134.130.169.31:12002",			# Local ip:port, use '*' for random port
 		remote = "134.130.169.98:12001",
 		header = "gtnet-skt:fake",			# 'gtnet-skt' or 'villas'. If not provided, 'villas' header will be used
+		endian = "big",						# Can be 'little' or 'small'. If not provided (default), little endianness logic will be applied
 		vectorize = 1,				# Number of samples to fetch per iteration from the socket
 		netem = {
 			enabled = false,
diff --git a/include/villas/node.h b/include/villas/node.h
index c24841832..32670f8f4 100644
--- a/include/villas/node.h
+++ b/include/villas/node.h
@@ -48,6 +48,8 @@ struct node
 	int vectorize;		/**< Number of messages to send / recv at once (scatter / gather) */
 	int affinity;		/**< CPU Affinity of this node */
 	
+	int endian;			/** Endianness of the data sent/received by the node */
+	
 	unsigned long sequence;	/**< This is a counter of received samples, in case the node-type does not generate sequence numbers itself. */
 
 	enum node_state {
diff --git a/include/villas/sample.h b/include/villas/sample.h
index 5d2db263d..4bd48938a 100644
--- a/include/villas/sample.h
+++ b/include/villas/sample.h
@@ -17,6 +17,14 @@
 #include <time.h>
 #include <sys/types.h>
 
+#ifdef __linux__
+  #include <byteswap.h>
+#elif defined(__PPC__) /* Xilinx toolchain */
+  #include <xil_io.h>
+  #define bswap_16(x)	Xil_EndianSwap16(x)
+  #define bswap_32(x)	Xil_EndianSwap32(x)
+#endif
+
 /* Forward declarations */
 struct pool;
 
@@ -45,6 +53,8 @@ struct sample {
 	
 	atomic_int refcnt;	/**< Reference counter. */
 	struct pool *pool;	/**< This sample is belong to this memory pool. */
+	
+	int endian;			/**< Endianess of data in the sample. */
 
 	/** All timestamps are seconds / nano seconds after 1.1.1970 UTC */
 	struct {
diff --git a/lib/cfg.c b/lib/cfg.c
index 33fe11ed6..3314bf324 100644
--- a/lib/cfg.c
+++ b/lib/cfg.c
@@ -274,7 +274,7 @@ int cfg_parse_nodelist(config_setting_t *cfg, struct list *list, struct list *al
 
 int cfg_parse_node(config_setting_t *cfg, struct list *nodes, struct settings *set)
 {
-	const char *type, *name;
+	const char *type, *name, *endian;
 	int ret;
 
 	struct node *n;
@@ -314,6 +314,17 @@ int cfg_parse_node(config_setting_t *cfg, struct list *nodes, struct settings *s
 	if (!config_setting_lookup_int(cfg, "affinity", &n->affinity))
 		n->affinity = set->affinity;
 	
+	if (!config_setting_lookup_string(cfg, "endian", &endian))
+		n->endian = LITTLE_ENDIAN;
+	else {
+		if(!strcmp(endian, "big"))
+			n->endian = BIG_ENDIAN;
+		else if (!strcmp(endian, "little"))
+			n->endian = LITTLE_ENDIAN;
+		else
+			cerror(cfg, "Invalid endianness type '%s' for node %s", endian, node_name(n));
+	}
+	
 	list_push(nodes, n);
 
 	return ret;
diff --git a/lib/nodes/socket.c b/lib/nodes/socket.c
index d28644836..64dfb90e1 100644
--- a/lib/nodes/socket.c
+++ b/lib/nodes/socket.c
@@ -275,6 +275,7 @@ int socket_read(struct node *n, struct sample *smps[], unsigned cnt)
 		smp->ts.received.tv_nsec = -1;
 
 		smp->length = length;
+		smp->endian = n->endian;
 
 		received = 1; /* GTNET-SKT sends every sample in a single packet */
 	}
diff --git a/lib/sample.c b/lib/sample.c
index f3040d3a0..a3dc5eb46 100644
--- a/lib/sample.c
+++ b/lib/sample.c
@@ -55,8 +55,14 @@ int sample_print(char *buf, size_t len, struct sample *s, int flags)
 		off += snprintf(buf + off, len - off, "(%u)", s->sequence);
 
 	if (flags & SAMPLE_VALUES) {
-		for (int i = 0; i < s->length; i++)
-			off += snprintf(buf + off, len - off, "\t%.6f", s->data[i].f);
+		for (int i = 0; i < s->length; i++) {
+			float display_float = s->data[i].f;
+			if(s->endian == BIG_ENDIAN) {
+				uint32_t * temp_int = (uint32_t *) &(display_float);
+				*temp_int = bswap_32(*temp_int);
+			}
+			off += snprintf(buf + off, len - off, "\t%.6f", display_float);
+		}
 	}
 
 	off += snprintf(buf + off, len - off, "\n");