summaryrefslogtreecommitdiff
path: root/src/ipcpd/unicast/fa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipcpd/unicast/fa.c')
-rw-r--r--src/ipcpd/unicast/fa.c195
1 files changed, 188 insertions, 7 deletions
diff --git a/src/ipcpd/unicast/fa.c b/src/ipcpd/unicast/fa.c
index b2eed7e5..2fc37d95 100644
--- a/src/ipcpd/unicast/fa.c
+++ b/src/ipcpd/unicast/fa.c
@@ -36,6 +36,7 @@
#include <ouroboros/errno.h>
#include <ouroboros/dev.h>
#include <ouroboros/ipcp-dev.h>
+#include <ouroboros/rib.h>
#include "dir.h"
#include "fa.h"
@@ -44,6 +45,7 @@
#include "dt.h"
#include "ca.h"
+#include <inttypes.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
@@ -55,6 +57,8 @@
#define FLOW_UPDATE 2
#define MSGBUFSZ 2048
+#define STAT_FILE_LEN 0
+
struct fa_msg {
uint64_t s_addr;
uint32_t r_eid;
@@ -79,6 +83,9 @@ struct cmd {
};
struct fa_flow {
+#ifdef IPCP_FLOW_STATS
+ time_t stamp;
+#endif
int r_eid; /* remote endpoint id */
uint64_t r_addr; /* remote address */
void * ctx; /* congestion avoidance context */
@@ -87,7 +94,9 @@ struct fa_flow {
struct {
pthread_rwlock_t flows_lock;
struct fa_flow flows[PROG_MAX_FLOWS];
-
+#ifdef IPCP_FLOW_STATS
+ size_t n_flows;
+#endif
int fd;
struct list_head cmds;
@@ -98,6 +107,156 @@ struct {
struct psched * psched;
} fa;
+static int fa_stat_read(const char * path,
+ char * buf,
+ size_t len)
+{
+#ifdef IPCP_FLOW_STATS
+ struct fa_flow * flow;
+ int fd;
+ char r_addrstr[20];
+ char tmstr[20];
+ char castr[1024];
+ struct tm * tm;
+
+ fd = atoi(path);
+
+ if (fd < 0 || fd > PROG_MAX_FLOWS)
+ return -1;
+
+ if (len < 1536)
+ return 0;
+
+ flow = &fa.flows[fd];
+
+ buf[0] = '\0';
+
+ pthread_rwlock_rdlock(&fa.flows_lock);
+
+ if (flow->stamp ==0) {
+ pthread_rwlock_unlock(&fa.flows_lock);
+ return 0;
+ }
+
+ sprintf(r_addrstr, "%" PRIu64, flow->r_addr);
+
+ tm = localtime(&flow->stamp);
+ strftime(tmstr, sizeof(tmstr), "%F %T", tm);
+
+ ca_print_stats(flow->ctx, castr, 1024);
+
+ sprintf(buf,
+ "Flow established at: %20s\n"
+ "Remote address: %20s\n"
+ "Local endpoint ID: %20d\n"
+ "Remote endpoint ID: %20d\n"
+ "%s",
+ tmstr, r_addrstr, fd, flow->r_eid,
+ castr);
+
+ pthread_rwlock_unlock(&fa.flows_lock);
+
+ return strlen(buf);
+#else
+ (void) path;
+ (void) buf;
+ (void) len;
+ return 0;
+#endif
+}
+
+static int fa_stat_readdir(char *** buf)
+{
+#ifdef IPCP_FLOW_STATS
+ char entry[RIB_PATH_LEN + 1];
+ size_t i;
+ int idx = 0;
+
+ pthread_rwlock_rdlock(&fa.flows_lock);
+
+ if (fa.n_flows < 1) {
+ pthread_rwlock_unlock(&fa.flows_lock);
+ return 0;
+ }
+
+ *buf = malloc(sizeof(**buf) * fa.n_flows);
+ if (*buf == NULL) {
+ pthread_rwlock_unlock(&fa.flows_lock);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < PROG_MAX_FLOWS; ++i) {
+ struct fa_flow * flow;
+
+ flow = &fa.flows[i];
+ if (flow->stamp == 0)
+ continue;
+
+ sprintf(entry, "%zu", i);
+
+ (*buf)[idx] = malloc(strlen(entry) + 1);
+ if ((*buf)[idx] == NULL) {
+ while (idx-- > 0)
+ free((*buf)[idx]);
+ free(buf);
+ pthread_rwlock_unlock(&fa.flows_lock);
+ return -ENOMEM;
+ }
+
+ strcpy((*buf)[idx++], entry);
+ }
+
+ assert((size_t) idx == fa.n_flows);
+
+ pthread_rwlock_unlock(&fa.flows_lock);
+
+ return idx;
+#else
+ (void) buf;
+ return 0;
+#endif
+}
+
+static int fa_stat_getattr(const char * path,
+ struct stat * st)
+{
+#ifdef IPCP_FLOW_STATS
+ int fd;
+ struct fa_flow * flow;
+
+ fd = atoi(path);
+
+ st->st_mode = S_IFREG | 0755;
+ st->st_nlink = 1;
+ st->st_uid = getuid();
+ st->st_gid = getgid();
+
+ flow = &fa.flows[fd];
+
+ pthread_rwlock_rdlock(&fa.flows_lock);
+
+ if (flow->stamp != 0) {
+ st->st_size = 1536;
+ st->st_mtime = flow->stamp;
+ } else {
+ st->st_size = 0;
+ st->st_mtime = 0;
+ }
+
+ pthread_rwlock_unlock(&fa.flows_lock);
+#else
+ (void) path;
+ (void) st;
+#endif
+ return 0;
+}
+
+static struct rib_ops r_ops = {
+ .read = fa_stat_read,
+ .readdir = fa_stat_readdir,
+ .getattr = fa_stat_getattr
+};
+
static void packet_handler(int fd,
qoscube_t qc,
struct shm_du_buff * sdb)
@@ -132,6 +291,9 @@ static void packet_handler(int fd,
static int fa_flow_init(struct fa_flow * flow)
{
+#ifdef IPCP_FLOW_STATS
+ struct timespec now;
+#endif
memset(flow, 0, sizeof(*flow));
flow->r_eid = -1;
@@ -141,6 +303,13 @@ static int fa_flow_init(struct fa_flow * flow)
if (flow->ctx == NULL)
return -1;
+#ifdef IPCP_FLOW_STATS
+ clock_gettime(CLOCK_REALTIME_COARSE, &now);
+
+ flow->stamp = now.tv_sec;
+
+ ++fa.n_flows;
+#endif
return 0;
}
@@ -152,6 +321,10 @@ static void fa_flow_fini(struct fa_flow * flow)
flow->r_eid = -1;
flow->r_addr = INVALID_ADDR;
+
+#ifdef IPCP_FLOW_STATS
+ --fa.n_flows;
+#endif
}
static void fa_post_packet(void * comp,
@@ -336,6 +509,7 @@ static void * fa_handle_packet(void * o)
int fa_init(void)
{
pthread_condattr_t cattr;
+ char fastr[256];
if (pthread_rwlock_init(&fa.flows_lock, NULL))
goto fail_rwlock;
@@ -358,8 +532,14 @@ int fa_init(void)
fa.fd = dt_reg_comp(&fa, &fa_post_packet, FA);
+ sprintf(fastr, "%s", FA);
+ if (rib_reg(fastr, &r_ops))
+ goto fail_rib_reg;
+
return 0;
+ fail_rib_reg:
+ pthread_cond_destroy(&fa.cond);
fail_cond:
pthread_condattr_destroy(&cattr);
fail_cattr:
@@ -586,6 +766,7 @@ static int fa_update_remote(int fd,
struct shm_du_buff * sdb;
qoscube_t qc = QOS_CUBE_BE;
struct fa_flow * flow;
+ uint64_t r_addr;
if (ipcp_sdb_reserve(&sdb, sizeof(*msg))) {
return -1;
@@ -603,15 +784,16 @@ static int fa_update_remote(int fd,
msg->r_eid = hton32(flow->r_eid);
msg->ece = hton16(ece);
- if (dt_write_packet(flow->r_addr, qc, fa.fd, sdb)) {
- pthread_rwlock_unlock(&fa.flows_lock);
- ipcp_sdb_release(sdb);
- return -1;
- }
+ r_addr = flow->r_addr;
pthread_rwlock_unlock(&fa.flows_lock);
+ if (dt_write_packet(r_addr, qc, fa.fd, sdb)) {
+ ipcp_sdb_release(sdb);
+ return -1;
+ }
+
return 0;
}
@@ -638,5 +820,4 @@ void fa_ecn_update(int eid,
if (update)
fa_update_remote(eid, ece);
-
}