summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlefranc2010-02-01 13:10:25 +0000
committerlefranc2010-02-01 13:10:25 +0000
commit88a4da8c6b759fcf55f44c82d188abfa2b3b5fd9 (patch)
tree7c30a1b225b925253a6253f68ed7ebdb763d7e3e
parent4f401c4dffa12d517cdd8e9d1e4e60dc09a87954 (diff)
cleo/appli/managerd: add VS_ETH_STATS MME
- unit tests included git-svn-id: svn+ssh://pessac/svn/cesar/trunk@6682 017c9cb6-072f-447c-8318-d5b54f68fe89
-rw-r--r--cleopatre/application/libmme/inc/libmme.h22
-rw-r--r--cleopatre/application/managerd/inc/bridge.h1
-rw-r--r--cleopatre/application/managerd/inc/vs_mme.h36
-rw-r--r--cleopatre/application/managerd/src/bridge.c2
-rw-r--r--cleopatre/application/managerd/src/vs_mme.c115
-rw-r--r--cleopatre/devkit/tests/managerd/utests/src/vs_mme_utests.c139
-rw-r--r--cleopatre/devkit/tests/managerd/utests/testfiles/net_dev7
7 files changed, 300 insertions, 22 deletions
diff --git a/cleopatre/application/libmme/inc/libmme.h b/cleopatre/application/libmme/inc/libmme.h
index b9ba8ae538..114f918358 100644
--- a/cleopatre/application/libmme/inc/libmme.h
+++ b/cleopatre/application/libmme/inc/libmme.h
@@ -29,22 +29,22 @@
typedef enum
{
- MME_TYPE_VS_GET_VERSION = 0xa000,
- MME_TYPE_VS_RESET = 0xa008,
- MME_TYPE_VS_GET_NVRAM = 0xa010,
- MME_TYPE_VS_GET_LOOPBACK = 0xa014,
- MME_TYPE_VS_SET_LOOPBACK = 0xa018,
- MME_TYPE_VS_GET_TONEMASK = 0xa01c,
- MME_TYPE_VS_GET_ETH_PHY = 0xa020,
- MME_TYPE_VS_GET_ETH_STATS = 0xa024,
+ MME_TYPE_VS_GET_VERSION = 0xa000,
+ MME_TYPE_VS_RESET = 0xa008,
+ MME_TYPE_VS_GET_NVRAM = 0xa010,
+ MME_TYPE_VS_GET_LOOPBACK = 0xa014,
+ MME_TYPE_VS_SET_LOOPBACK = 0xa018,
+ MME_TYPE_VS_GET_TONEMASK = 0xa01c,
+ MME_TYPE_VS_GET_ETH_PHY = 0xa020,
+ MME_TYPE_VS_ETH_STATS = 0xa024,
MME_TYPE_VS_SNIFFER = 0xa02c,
MME_TYPE_VS_GET_STATUS = 0xa030,
MME_TYPE_VS_GET_TONEMAP = 0xa034,
MME_TYPE_VS_GET_SNR = 0xa038,
MME_TYPE_VS_GET_SPECTRUM = 0xa03c,
- MME_TYPE_VS_GET_LINK_STATS = 0xa040,
- MME_TYPE_VS_GET_AMP_MAP = 0xa044,
- MME_TYPE_VS_GET_STATS = 0xa048,
+ MME_TYPE_VS_GET_LINK_STATS= 0xa040,
+ MME_TYPE_VS_GET_AMP_MAP = 0xa044,
+ MME_TYPE_VS_GET_STATS = 0xa048,
} mme_type_t;
#define MME_TYPE_REQ 0x0000
diff --git a/cleopatre/application/managerd/inc/bridge.h b/cleopatre/application/managerd/inc/bridge.h
index c18a008e3b..a5f535833c 100644
--- a/cleopatre/application/managerd/inc/bridge.h
+++ b/cleopatre/application/managerd/inc/bridge.h
@@ -27,6 +27,7 @@
/** Interfaces name */
#define BR_IFNAME "br0"
#define PLC_IFNAME "plc0"
+#define ETH_IFNAME "eth0"
#define BROADCAST_ADDR "\xff\xff\xff\xff\xff\xff"
diff --git a/cleopatre/application/managerd/inc/vs_mme.h b/cleopatre/application/managerd/inc/vs_mme.h
index 0cddf0b0da..4d3832e75c 100644
--- a/cleopatre/application/managerd/inc/vs_mme.h
+++ b/cleopatre/application/managerd/inc/vs_mme.h
@@ -29,6 +29,8 @@
#define SPC300_ID 0x0001
#define PLC_VERSION_PATH "/proc/net/plc/version"
+#define MME_RESULT_SUCCESS 0
+#define MME_RESULT_FAILURE 1
typedef struct {
uint8_t oui[3];
@@ -41,6 +43,40 @@ typedef struct {
uint8_t av_stack_alternate[64];
} __attribute__ ((__packed__)) vs_get_version_cnf_t;
+typedef enum {
+ ETH_STATS_COMMAND_GET = 0,
+ ETH_STATS_COMMAND_RESET,
+ ETH_STATS_COMMAND_NB
+} vs_eth_stats_command_t;
+
+typedef struct {
+ uint8_t oui[3];
+ uint8_t command;
+} __attribute__ ((__packed__)) vs_eth_stats_req_t;
+
+typedef struct {
+ uint8_t oui[3];
+ uint8_t result;
+ uint32_t rx_bytes_low;
+ uint32_t rx_bytes_high;
+ uint32_t rx_packets_low;
+ uint32_t rx_packets_high;
+ uint32_t rx_errors;
+ uint32_t rx_dropped;
+ uint32_t rx_overruns;
+ uint32_t rx_frames;
+ uint32_t tx_bytes_low;
+ uint32_t tx_bytes_high;
+ uint32_t tx_packets_low;
+ uint32_t tx_packets_high;
+ uint32_t tx_errors;
+ uint32_t tx_dropped;
+ uint32_t tx_fifo;
+ uint32_t tx_collisions;
+ uint32_t tx_carrier;
+} __attribute__ ((__packed__)) vs_eth_stats_cnf_t;
+
extern enum bridge_status vs_mme_get_version (struct managerd_ctx *ctx, MME_t *request, MME_t * confirm, int len);
+extern enum bridge_status vs_mme_eth_stats (struct managerd_ctx *ctx, MME_t *request, MME_t * confirm, int len);
#endif /* VS_MME_H */
diff --git a/cleopatre/application/managerd/src/bridge.c b/cleopatre/application/managerd/src/bridge.c
index 0bea560395..f9aff80f41 100644
--- a/cleopatre/application/managerd/src/bridge.c
+++ b/cleopatre/application/managerd/src/bridge.c
@@ -67,6 +67,8 @@ enum bridge_status bridge_processing(struct managerd_ctx *ctx, uint8_t *buffer,
{
case MME_TYPE_VS_GET_VERSION | MME_TYPE_REQ:
return vs_mme_get_version (ctx, mmehdr, confirm, MAX_PKT_LEN);
+ case MME_TYPE_VS_ETH_STATS | MME_TYPE_REQ:
+ return vs_mme_eth_stats (ctx, mmehdr, confirm, MAX_PKT_LEN);
default:
break;
}
diff --git a/cleopatre/application/managerd/src/vs_mme.c b/cleopatre/application/managerd/src/vs_mme.c
index b9afe32948..76e38345c1 100644
--- a/cleopatre/application/managerd/src/vs_mme.c
+++ b/cleopatre/application/managerd/src/vs_mme.c
@@ -21,12 +21,24 @@
#include <stdio.h>
#include <string.h>
+#include <syslog.h>
#include "bridge.h"
#include "vs_mme.h"
#define FIRMWARE_LABEL "irmware"
+static void _prepare_confirm (struct managerd_ctx *ctx, MME_t *request, MME_t *confirm, int len)
+{
+ memset (confirm, '\0', len);
+ memcpy (confirm->mme_dest, request->mme_src, ETH_ALEN);
+ memcpy (confirm->mme_src, ctx->br_mac_addr, ETH_ALEN);
+ confirm->mtype = request->mtype;
+ confirm->mmv = request->mmv;
+ confirm->mmtype = (request->mmtype & ~MME_TYPE_MASK) | MME_TYPE_CNF;
+ confirm->fmi = 0;
+}
+
/**
* Send a VS_GET_VERSION MME to BR interface.
*
@@ -54,18 +66,12 @@ enum bridge_status vs_mme_get_version (struct managerd_ctx *ctx, MME_t *request,
if(memcmp ((char *)request + sizeof(MME_t), OUI_SPIDCOM, 3))
return TO_DROP;
- /* prepare ethernet header */
- memset (confirm, '\0', len);
- memcpy (confirm->mme_dest, request->mme_src, ETH_ALEN);
- memcpy (confirm->mme_src, ctx->br_mac_addr, ETH_ALEN);
- confirm->mtype = request->mtype;
- confirm->mmv = request->mmv;
- confirm->mmtype = MME_TYPE_VS_GET_VERSION | MME_TYPE_CNF;
- confirm->fmi = 0;
+ get_version_cnf = (vs_get_version_cnf_t *)((unsigned char*)confirm + sizeof(MME_t));
+
+ /* prepare confirm packet */
+ _prepare_confirm (ctx, request, confirm, len);
/* set get_version inside confirm buffer */
- get_version_cnf = (vs_get_version_cnf_t *)((unsigned char*)confirm + sizeof(MME_t));
- /* fill get_version */
memcpy (get_version_cnf->oui, OUI_SPIDCOM, 3);
get_version_cnf->result = 0;
get_version_cnf->device_id = SPC300_ID;
@@ -102,3 +108,92 @@ enum bridge_status vs_mme_get_version (struct managerd_ctx *ctx, MME_t *request,
bridge_send_to_br (ctx, (uint8_t *)confirm, sizeof(MME_t) + sizeof(vs_get_version_cnf_t));
return TO_DROP;
}
+
+/**
+ * Send a VS_ETH_STATS MME to BR interface.
+ *
+ * \param ctx managerd context.
+ * \param request MME containg VS_ETH_STATS request.
+ * \param confirm MME buffer to put VS_ETH_STATS confirm.
+ * \param len confirm buffer length.
+ * \return error code.
+ */
+enum bridge_status vs_mme_eth_stats (struct managerd_ctx *ctx, MME_t *request, MME_t *confirm, int len)
+{
+ vs_eth_stats_req_t *eth_stats_req;
+ vs_eth_stats_cnf_t *eth_stats_cnf;
+
+ FILE *fp;
+ char tmp_buffer[256];
+ char name[64], *ptr;
+ unsigned long long rx_bytes, rx_packets, tx_bytes, tx_packets;
+
+ assert (NULL != ctx);
+ assert (NULL != request);
+ assert (NULL != confirm);
+ assert (len >= sizeof(vs_eth_stats_cnf_t) + sizeof(MME_t));
+
+ eth_stats_req = (vs_eth_stats_req_t *)((unsigned char*)request + sizeof(MME_t));
+ eth_stats_cnf = (vs_eth_stats_cnf_t *)((unsigned char*)confirm + sizeof(MME_t));
+
+ if(memcmp (eth_stats_req->oui, OUI_SPIDCOM, 3))
+ return TO_DROP;
+
+ /* prepare confirm packet */
+ _prepare_confirm (ctx, request, confirm, len);
+ memcpy (eth_stats_cnf->oui, OUI_SPIDCOM, 3);
+ eth_stats_cnf->result = MME_RESULT_FAILURE;
+
+ /* check request type */
+ if(ETH_STATS_COMMAND_GET == eth_stats_req->command)
+ {
+ if((fp = fopen ("/proc/net/dev", "r")) == NULL)
+ goto failed;
+ /* read the 2 comment lines */
+ fgets (tmp_buffer, sizeof(tmp_buffer), fp);
+ fgets (tmp_buffer, sizeof(tmp_buffer), fp);
+ /* read all line until found eth0 */
+ while(fgets (tmp_buffer, sizeof(tmp_buffer), fp))
+ {
+ if((ptr = strchr (tmp_buffer, ':')) == NULL)
+ continue;
+ *ptr = '\0';
+ ptr++;
+ if((sscanf (tmp_buffer, "%s", name) == 1)
+ && !strncmp (name, ETH_IFNAME, strlen(ETH_IFNAME))
+ && (sscanf (ptr, "%Lu %Lu %lu %lu %lu %lu %*s %*s %Lu %Lu %lu %lu %lu %lu %lu %*s",
+ &rx_bytes,
+ &rx_packets,
+ (unsigned long int *)&eth_stats_cnf->rx_errors,
+ (unsigned long int *)&eth_stats_cnf->rx_dropped,
+ (unsigned long int *)&eth_stats_cnf->rx_overruns,
+ (unsigned long int *)&eth_stats_cnf->rx_frames,
+ &tx_bytes,
+ &tx_packets,
+ (unsigned long int *)&eth_stats_cnf->tx_errors,
+ (unsigned long int *)&eth_stats_cnf->tx_dropped,
+ (unsigned long int *)&eth_stats_cnf->tx_fifo,
+ (unsigned long int *)&eth_stats_cnf->tx_collisions,
+ (unsigned long int *)&eth_stats_cnf->tx_carrier) == 13))
+ {
+ eth_stats_cnf->rx_bytes_low = rx_bytes & 0xffffffff;
+ eth_stats_cnf->rx_bytes_high = (rx_bytes & 0xffffffff00000000LL) >> 32;
+ eth_stats_cnf->rx_packets_low = rx_packets & 0xffffffff;
+ eth_stats_cnf->rx_packets_high = (rx_packets & 0xffffffff00000000LL) >> 32;
+ eth_stats_cnf->tx_bytes_low = tx_bytes & 0xffffffff;
+ eth_stats_cnf->tx_bytes_high = (tx_bytes & 0xffffffff00000000LL) >> 32;
+ eth_stats_cnf->tx_packets_low = tx_packets & 0xffffffff;
+ eth_stats_cnf->tx_packets_high = (tx_packets & 0xffffffff00000000LL) >> 32;
+
+ //printf ( "name='%s', rx_bytes=%llu rx_errors=%lu\n", name, eth_stats_cnf->rx_bytes_low, (unsigned long int)eth_stats_cnf->rx_errors);
+ eth_stats_cnf->result = MME_RESULT_SUCCESS;
+ break;
+ }
+ }
+ fclose (fp);
+ }
+
+ failed:
+ bridge_send_to_br (ctx, (uint8_t *)confirm, sizeof(MME_t) + sizeof(vs_eth_stats_cnf_t));
+ return TO_DROP;
+}
diff --git a/cleopatre/devkit/tests/managerd/utests/src/vs_mme_utests.c b/cleopatre/devkit/tests/managerd/utests/src/vs_mme_utests.c
index ad585ceea1..eb555d4765 100644
--- a/cleopatre/devkit/tests/managerd/utests/src/vs_mme_utests.c
+++ b/cleopatre/devkit/tests/managerd/utests/src/vs_mme_utests.c
@@ -42,6 +42,7 @@
#define PLC_FIRMWARE_VERSION "0.1-rc3-1-unit_test"
#define PLC_VERSION_FILE "testfiles/plc_version"
+#define NET_DEV_FILE "testfiles/net_dev"
#define BR_MAC_ADDR "\x00\x13\xd7\x00\x00\x10"
@@ -56,6 +57,14 @@ static struct check_ctx {
} check_ctx;
+enum test_id {
+ TEST_GET_VERSION = 0,
+ TEST_ETH_STATS,
+ TEST_NB
+};
+
+enum test_id test_id;
+
/** local variables */
static struct managerd_ctx managerd_ctx;
static struct managerd_ctx *ctx = &managerd_ctx;
@@ -85,7 +94,17 @@ void __assert_fail (__const char *__assertion, __const char *__file,
FILE *fopen (const char *path, const char *mode)
{
- test_fd = open (PLC_VERSION_FILE, O_RDONLY);
+ switch(test_id)
+ {
+ case TEST_GET_VERSION:
+ test_fd = open (PLC_VERSION_FILE, O_RDONLY);
+ break;
+ case TEST_ETH_STATS:
+ test_fd = open (NET_DEV_FILE, O_RDONLY);
+ break;
+ default:
+ return NULL;
+ }
return fdopen (test_fd, "r");
}
@@ -254,6 +273,9 @@ START_TEST (test_get_version_success)
{
int result;
vs_get_version_cnf_t *get_version_cnf;
+
+ test_id = TEST_GET_VERSION;
+
get_version_cnf = (vs_get_version_cnf_t *)((unsigned char*)confirm + sizeof(MME_t));
/* fill request */
memset (request, '\0', 1024);
@@ -292,10 +314,125 @@ TCase *vs_get_version_tcase (void)
return tc;
}
+/* check param input error */
+START_TEST (test_eth_stats_param_1)
+{
+ check_ctx.test_id = 1;
+ if(0 == setjmp (check_ctx.jmp_env))
+ {
+ vs_mme_eth_stats (NULL, request, confirm, 1024);
+ fail ("vs_eth_stats ctx = NULL (1)");
+ }
+ fail_unless ((check_ctx.test_id == check_ctx.assert_id),
+ "vs_eth_stats ctx = NULL (2)");
+}
+END_TEST
+
+START_TEST (test_eth_stats_param_2)
+{
+ check_ctx.test_id = 2;
+ if(0 == setjmp (check_ctx.jmp_env))
+ {
+ vs_mme_eth_stats (ctx, NULL, confirm, 1024);
+ fail ("vs_eth_stats request = NULL (1)");
+ }
+ fail_unless ((check_ctx.test_id == check_ctx.assert_id),
+ "vs_eth_stats request = NULL (2)");
+}
+END_TEST
+
+START_TEST (test_eth_stats_param_3)
+{
+ check_ctx.test_id = 3;
+ if(0 == setjmp (check_ctx.jmp_env))
+ {
+ vs_mme_eth_stats (ctx, request, NULL, 1024);
+ fail ("vs_eth_stats confirm = NULL (1)");
+ }
+ fail_unless ((check_ctx.test_id == check_ctx.assert_id),
+ "vs_eth_stats confirm = NULL (2)");
+}
+END_TEST
+
+START_TEST (test_eth_stats_param_4)
+{
+ check_ctx.test_id = 4;
+ if(0 == setjmp (check_ctx.jmp_env))
+ {
+ vs_mme_eth_stats (ctx, request, confirm, sizeof(vs_eth_stats_cnf_t) + sizeof(MME_t) - 1);
+ fail ("vs_eth_stats len too small (1)");
+ }
+ fail_unless ((check_ctx.test_id == check_ctx.assert_id),
+ "vs_eth_stats len too small (2)");
+}
+END_TEST
+
+START_TEST (test_eth_stats_get_success)
+{
+ int result;
+ vs_eth_stats_req_t *eth_stats_req;
+ vs_eth_stats_cnf_t *eth_stats_cnf;
+
+ test_id = TEST_ETH_STATS;
+
+ eth_stats_req = (vs_eth_stats_req_t *)((unsigned char*)request + sizeof(MME_t));
+ eth_stats_cnf = (vs_eth_stats_cnf_t *)((unsigned char*)confirm + sizeof(MME_t));
+ /* fill request */
+ memset (request, '\0', 1024);
+ memcpy (request->mme_src, "\x00\x13\xd7\x00\x00\x20", ETH_ALEN);
+ memcpy (request->mme_dest, BROADCAST_ADDR, ETH_ALEN);
+ request->mtype = htons (MME_TYPE);
+ request->mmtype = MME_TYPE_VS_ETH_STATS | MME_TYPE_REQ;
+ memcpy (eth_stats_req->oui, OUI_SPIDCOM, 3);
+ eth_stats_req->command = 0; /* get command */
+
+ fail_unless ((vs_mme_eth_stats (ctx, request, confirm, 1024) == TO_DROP)
+ && !memcmp (confirm->mme_dest, request->mme_src, ETH_ALEN)
+ && !memcmp (confirm->mme_src, ctx->br_mac_addr, ETH_ALEN)
+ && (confirm->mtype == request->mtype)
+ && (confirm->mmtype == (MME_TYPE_VS_ETH_STATS | MME_TYPE_CNF))
+ && !memcmp (eth_stats_cnf->oui, OUI_SPIDCOM, 3)
+ && (eth_stats_cnf->result == MME_RESULT_SUCCESS)
+ && (eth_stats_cnf->rx_bytes_low == (111111111111LL & 0xffffffff))
+ && (eth_stats_cnf->rx_bytes_high == ((111111111111LL & 0xffffffff00000000LL) >> 32))
+ && (eth_stats_cnf->rx_packets_low == (2222222222LL & 0xffffffff))
+ && (eth_stats_cnf->rx_packets_high == ((2222222222LL & 0xffffffff00000000LL) >> 32))
+ && (eth_stats_cnf->rx_errors == 303)
+ && (eth_stats_cnf->rx_dropped == 404)
+ && (eth_stats_cnf->rx_overruns == 505)
+ && (eth_stats_cnf->rx_frames == 606)
+ && (eth_stats_cnf->tx_bytes_low == (333333333333LL & 0xffffffff))
+ && (eth_stats_cnf->tx_bytes_high == ((333333333333LL & 0xffffffff00000000LL) >> 32))
+ && (eth_stats_cnf->tx_packets_low == (4444444444LL & 0xffffffff))
+ && (eth_stats_cnf->tx_packets_high == ((4444444444LL & 0xffffffff00000000LL) >> 32))
+ && (eth_stats_cnf->tx_errors == 909)
+ && (eth_stats_cnf->tx_dropped == 1010)
+ && (eth_stats_cnf->tx_fifo == 1111)
+ && (eth_stats_cnf->tx_collisions == 1212)
+ && (eth_stats_cnf->tx_carrier == 1313)
+ ,
+ "vs_eth_stats_get success");
+}
+END_TEST
+
+TCase *vs_eth_stats_tcase (void)
+{
+ TCase *tc = tcase_create ("vs_eth_stats");
+ tcase_add_checked_fixture (tc, setup, teardown);
+ // check input param
+ tcase_add_test (tc, test_eth_stats_param_1);
+ tcase_add_test (tc, test_eth_stats_param_2);
+ tcase_add_test (tc, test_eth_stats_param_3);
+ tcase_add_test (tc, test_eth_stats_param_4);
+ tcase_add_test (tc, test_eth_stats_get_success);
+ return tc;
+}
+
Suite* vs_mme_suite(void)
{
Suite *s = suite_create ("vs_mme");
suite_add_tcase (s, vs_get_version_tcase ());
+ suite_add_tcase (s, vs_eth_stats_tcase ());
return s;
}
diff --git a/cleopatre/devkit/tests/managerd/utests/testfiles/net_dev b/cleopatre/devkit/tests/managerd/utests/testfiles/net_dev
new file mode 100644
index 0000000000..9d0f24c990
--- /dev/null
+++ b/cleopatre/devkit/tests/managerd/utests/testfiles/net_dev
@@ -0,0 +1,7 @@
+Inter-| Receive | Transmit
+ face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
+ lo: 1074523 36505 0 0 0 0 0 0 1074523 36505 0 0 0 0 0 0
+ eth0:111111111111 2222222222 303 404 505 606 707 808 333333333333 4444444444 909 1010 1111 1212 1313 1414
+ br0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ plc0: 5914 66 0 0 0 0 0 0 118734 142 0 0 0 0 0 0
+