summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/CMakeLists.txt10
-rw-r--r--src/lib/config.h.in1
-rw-r--r--src/lib/dev.c20
-rw-r--r--src/lib/frct.c141
-rw-r--r--src/lib/rib.c18
5 files changed, 173 insertions, 17 deletions
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index 76d0530d..022c5cca 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -219,6 +219,16 @@ set(ACK_WHEEL_SLOTS 128 CACHE STRING
set(ACK_WHEEL_RESOLUTION 20 CACHE STRING
"Minimum acknowledgment delay (ns), as a power to 2")
+if (HAVE_FUSE)
+ set(PROC_FLOW_STATS TRUE CACHE BOOL
+ "Enable flow statistics tracking for application flows")
+ if (PROC_FLOW_STATS)
+ message(STATUS "Application flow statistics enabled")
+ else ()
+ message(STATUS "Application flow statistics disabled")
+ endif ()
+endif ()
+
set(SOURCE_FILES_DEV
# Add source files here
cacep.c
diff --git a/src/lib/config.h.in b/src/lib/config.h.in
index 17213a57..5c5b6caf 100644
--- a/src/lib/config.h.in
+++ b/src/lib/config.h.in
@@ -56,6 +56,7 @@
#cmakedefine HAVE_FUSE
#ifdef HAVE_FUSE
#define FUSE_PREFIX "@FUSE_PREFIX@"
+#cmakedefine PROC_FLOW_STATS
#endif
#define PTHREAD_COND_CLOCK @PTHREAD_COND_CLOCK@
diff --git a/src/lib/dev.c b/src/lib/dev.c
index ec4561b2..fbbc096d 100644
--- a/src/lib/dev.c
+++ b/src/lib/dev.c
@@ -44,6 +44,9 @@
#include <ouroboros/shm_rbuff.h>
#include <ouroboros/utils.h>
#include <ouroboros/fqueue.h>
+#ifdef PROC_FLOW_STATS
+#include <ouroboros/rib.h>
+#endif
#include <stdlib.h>
#include <string.h>
@@ -361,7 +364,9 @@ static void init(int argc,
{
const char * prog = argv[0];
int i;
-
+#ifdef PROC_FLOW_STATS
+ char procstr[32];
+#endif
(void) argc;
(void) envp;
@@ -437,6 +442,11 @@ static void init(int argc,
if (timerwheel_init() < 0)
goto fail_timerwheel;
+#if defined PROC_FLOW_STATS
+ sprintf(procstr, "proc.%d", getpid());
+ /* Don't bail, it just won't show metrics */
+ rib_init(procstr);
+#endif
return;
fail_timerwheel:
@@ -470,7 +480,13 @@ static void init(int argc,
static void fini(void)
{
- int i = 0;
+ int i = 0;
+#ifdef PROC_FLOW_STATS
+ char procstr[32];
+
+ sprintf(procstr, "proc.%d", getpid());
+ rib_fini();
+#endif
if (ai.fds == NULL)
return;
diff --git a/src/lib/frct.c b/src/lib/frct.c
index 7aaf037c..5313e4da 100644
--- a/src/lib/frct.c
+++ b/src/lib/frct.c
@@ -20,10 +20,12 @@
* Foundation, Inc., http://www.fsf.org/about/contact/.
*/
-#define DELT_RDV (100 * MILLION) /* ns */
-#define MAX_RDV (1 * BILLION) /* ns */
+#define DELT_RDV (100 * MILLION) /* ns */
+#define MAX_RDV (1 * BILLION) /* ns */
-#define FRCT_PCILEN (sizeof(struct frct_pci))
+#define FRCT "frct"
+#define FRCT_PCILEN (sizeof(struct frct_pci))
+#define FRCT_NAME_STRLEN 32
struct frct_cr {
uint32_t lwe; /* Left window edge */
@@ -84,6 +86,103 @@ struct frct_pci {
uint32_t ackno;
} __attribute__((packed));
+#ifdef PROC_FLOW_STATS
+
+static int frct_rib_read(const char * path,
+ char * buf,
+ size_t len)
+{
+ struct timespec now;
+ char * entry;
+ struct flow * flow;
+ struct frcti * frcti;
+ int fd;
+
+ (void) len;
+
+ entry = strstr(path, RIB_SEPARATOR);
+ assert(entry);
+ *entry = '\0';
+
+ fd = atoi(path);
+
+ flow = &ai.flows[fd];
+
+ clock_gettime(PTHREAD_COND_CLOCK, &now);
+
+ pthread_rwlock_rdlock(&ai.lock);
+
+ frcti = flow->frcti;
+
+ pthread_rwlock_rdlock(&frcti->lock);
+
+ sprintf(buf,
+ "Maximum packet lifetime (ns): %20ld\n"
+ "Max time to Ack (ns): %20ld\n"
+ "Max time to Retransmit (ns): %20ld\n"
+ "Smoothed rtt (ns): %20ld\n"
+ "RTT standard deviation (ns): %20ld\n"
+ "Retransmit timeout RTO (ns): %20ld\n"
+ "Sender left window edge: %20u\n"
+ "Sender right window edge: %20u\n"
+ "Sender inactive (ns): %20ld\n"
+ "Sender current sequence number: %20u\n"
+ "Receiver left window edge: %20u\n"
+ "Receiver right window edge: %20u\n"
+ "Receiver inactive (ns): %20ld\n"
+ "Receiver last ack: %20u\n",
+ frcti->mpl,
+ frcti->a,
+ frcti->r,
+ frcti->srtt,
+ frcti->mdev,
+ frcti->rto,
+ frcti->snd_cr.lwe,
+ frcti->snd_cr.rwe,
+ ts_diff_ns(&frcti->snd_cr.act, &now),
+ frcti->snd_cr.seqno,
+ frcti->rcv_cr.lwe,
+ frcti->rcv_cr.rwe,
+ ts_diff_ns(&frcti->rcv_cr.act, &now),
+ frcti->rcv_cr.seqno);
+
+ pthread_rwlock_unlock(&flow->frcti->lock);
+
+ pthread_rwlock_unlock(&ai.lock);
+
+ return strlen(buf);
+}
+
+static int frct_rib_readdir(char *** buf)
+{
+ *buf = malloc(sizeof(**buf));
+
+ (*buf)[0] = strdup("frct");
+
+ return 1;
+}
+
+static int frct_rib_getattr(const char * path,
+ struct rib_attr * attr)
+{
+ (void) path;
+ (void) attr;
+
+ attr->size = 1024;
+ attr->mtime = 0;
+
+ return 0;
+}
+
+
+static struct rib_ops r_ops = {
+ .read = frct_rib_read,
+ .readdir = frct_rib_readdir,
+ .getattr = frct_rib_getattr
+};
+
+#endif /* PROC_FLOW_STATS */
+
static bool before(uint32_t seq1,
uint32_t seq2)
{
@@ -205,14 +304,16 @@ static void __send_rdv(int fd)
static struct frcti * frcti_create(int fd)
{
- struct frcti * frcti;
- ssize_t idx;
- struct timespec now;
- time_t mpl;
- time_t a;
- time_t r;
- pthread_condattr_t cattr;
-
+ struct frcti * frcti;
+ ssize_t idx;
+ struct timespec now;
+ time_t mpl;
+ time_t a;
+ time_t r;
+ pthread_condattr_t cattr;
+#ifdef PROC_FLOW_STATS
+ char frctstr[FRCT_NAME_STRLEN + 1];
+#endif
frcti = malloc(sizeof(*frcti));
if (frcti == NULL)
goto fail_malloc;
@@ -233,6 +334,13 @@ static struct frcti * frcti_create(int fd)
if (pthread_cond_init(&frcti->cond, &cattr))
goto fail_cond;
+#ifdef PROC_FLOW_STATS
+ sprintf(frctstr, "%d", fd);
+ if (rib_reg(frctstr, &r_ops))
+ goto fail_rib_reg;
+#endif
+ pthread_condattr_destroy(&cattr);
+
for (idx = 0; idx < RQ_SIZE; ++idx)
frcti->rq[idx] = -1;
@@ -269,9 +377,13 @@ static struct frcti * frcti_create(int fd)
return frcti;
+#ifdef PROC_FLOW_STATS
+ fail_rib_reg:
+ pthread_cond_destroy(&frcti->cond);
+#endif
fail_cond:
pthread_condattr_destroy(&cattr);
-fail_cattr:
+ fail_cattr:
pthread_mutex_destroy(&frcti->mtx);
fail_mutex:
pthread_rwlock_destroy(&frcti->lock);
@@ -283,6 +395,11 @@ fail_cattr:
static void frcti_destroy(struct frcti * frcti)
{
+#ifdef PROC_FLOW_STATS
+ char frctstr[FRCT_NAME_STRLEN + 1];
+ sprintf(frctstr, "%d", frcti->fd);
+ rib_unreg(frctstr);
+#endif
pthread_cond_destroy(&frcti->cond);
pthread_mutex_destroy(&frcti->mtx);
pthread_rwlock_destroy(&frcti->lock);
diff --git a/src/lib/rib.c b/src/lib/rib.c
index dfac69d7..8fda19d4 100644
--- a/src/lib/rib.c
+++ b/src/lib/rib.c
@@ -286,8 +286,17 @@ int rib_init(const char * mountpt)
NULL};
struct fuse_args args = FUSE_ARGS_INIT(3, argv);
+ if (access("/dev/fuse", R_OK))
+ goto fail;
+
if (stat(FUSE_PREFIX, &st) == -1)
- return -1;
+ goto fail;
+
+ /* This is crap to allow IPCP RIB to remount to a different name */
+ if (strlen(rib.mnt) > 0) {
+ fuse_unmount(rib.mnt, rib.ch);
+ rmdir(rib.mnt);
+ }
sprintf(rib.mnt, FUSE_PREFIX "/%s", mountpt);
@@ -295,13 +304,13 @@ int rib_init(const char * mountpt)
switch(errno) {
case ENOENT:
if (mkdir(rib.mnt, 0777))
- return -1;
+ goto fail_mnt;
break;
case ENOTCONN:
fuse_unmount(rib.mnt, rib.ch);
break;
default:
- return -1;
+ goto fail_mnt;
}
fuse_opt_parse(&args, NULL, NULL, NULL);
@@ -335,6 +344,9 @@ int rib_init(const char * mountpt)
fail_mount:
fuse_opt_free_args(&args);
rmdir(rib.mnt);
+ fail_mnt:
+ memset(rib.mnt, 0, RIB_PATH_LEN + 1);
+ fail:
return -1;
#else
(void) mountpt;