summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Staessens <dimitri@ouroboros.rocks>2021-06-29 20:11:37 +0200
committerSander Vrijders <sander@ouroboros.rocks>2021-06-30 09:20:15 +0200
commit7c0c62706f2ae9821dc779db268a28ef986730fe (patch)
treeabe6a2204b93f2070d6270c472ec0d74693657a2
parent55e182b5b323c049ea49c79c2d68c8547940c62b (diff)
downloadouroboros-7c0c62706f2ae9821dc779db268a28ef986730fe.zip
ouroboros-7c0c62706f2ae9821dc779db268a28ef986730fe.tar.gz
lib: Application RIB with FRCT statistics
Application flows can now be monitored from the RIB, exposing FRCT statistics (window edges, retransmission timeout, rtt estimate, etc). Application RIB requires user permissions to be able to access /dev/fuse. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
-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 76d0530..022c5cc 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 17213a5..5c5b6ca 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 ec4561b..fbbc096 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 7aaf037..5313e4d 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 dfac69d..8fda19d 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;