diff options
-rw-r--r-- | src/lib/CMakeLists.txt | 10 | ||||
-rw-r--r-- | src/lib/config.h.in | 1 | ||||
-rw-r--r-- | src/lib/dev.c | 20 | ||||
-rw-r--r-- | src/lib/frct.c | 141 | ||||
-rw-r--r-- | src/lib/rib.c | 18 |
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; |