summaryrefslogtreecommitdiff
path: root/src/ipcpd/normal
diff options
context:
space:
mode:
authordimitri staessens <[email protected]>2017-08-28 18:54:22 +0200
committerdimitri staessens <[email protected]>2017-08-28 20:49:34 +0200
commit9de8dc4948cf7ce239232aae0889c39ffa39ede2 (patch)
tree396295b2d36f69ee55e5080e556891f11210aed8 /src/ipcpd/normal
parent176698e8c2fd7ab8007b8074515d6144e7177d8e (diff)
downloadouroboros-9de8dc4948cf7ce239232aae0889c39ffa39ede2.tar.gz
ouroboros-9de8dc4948cf7ce239232aae0889c39ffa39ede2.zip
tools: Add tool to connect IPCP components
This enables user-written tools to instruct IPCPs to establish and tear down connections (a.k.a. adjacencies) between its internal components (Management and Data Transfer). For more info, do "irm ipcp connect" or "irm ipcp disconnect" on the command line. This commit exposes a deletion bug in the RIB where FSO's fail to unpack/parse. This will be fixed when the RIB is deprecated.
Diffstat (limited to 'src/ipcpd/normal')
-rw-r--r--src/ipcpd/normal/ae.h9
-rw-r--r--src/ipcpd/normal/connmgr.c127
-rw-r--r--src/ipcpd/normal/connmgr.h6
-rw-r--r--src/ipcpd/normal/dt.c3
-rw-r--r--src/ipcpd/normal/enroll.c14
-rw-r--r--src/ipcpd/normal/enroll.h3
-rw-r--r--src/ipcpd/normal/main.c5
7 files changed, 136 insertions, 31 deletions
diff --git a/src/ipcpd/normal/ae.h b/src/ipcpd/normal/ae.h
index 4534cefa..3d3bdc27 100644
--- a/src/ipcpd/normal/ae.h
+++ b/src/ipcpd/normal/ae.h
@@ -27,6 +27,8 @@
#include "dt.h"
+#define DST_MAX_STRLEN 64
+
enum ae_id {
AEID_DT = 0,
AEID_ENROLL,
@@ -36,9 +38,10 @@ enum ae_id {
struct conn {
struct conn_info conn_info;
- struct flow_info {
- int fd;
- qosspec_t qs;
+ struct {
+ char dst[DST_MAX_STRLEN + 1];
+ int fd;
+ qosspec_t qs;
} flow_info;
};
diff --git a/src/ipcpd/normal/connmgr.c b/src/ipcpd/normal/connmgr.c
index b6e5e31a..11f83247 100644
--- a/src/ipcpd/normal/connmgr.c
+++ b/src/ipcpd/normal/connmgr.c
@@ -48,7 +48,7 @@ enum connmgr_state {
CONNMGR_RUNNING
};
-struct ae_conn {
+struct conn_el {
struct list_head next;
struct conn conn;
};
@@ -58,15 +58,17 @@ struct ae {
struct conn_info info;
struct list_head conns;
+ struct list_head pending;
+
pthread_cond_t cond;
pthread_mutex_t lock;
};
struct {
- struct ae aes[AEID_MAX];
- enum connmgr_state state;
+ struct ae aes[AEID_MAX];
+ enum connmgr_state state;
- pthread_t acceptor;
+ pthread_t acceptor;
} connmgr;
static int get_id_by_name(const char * name)
@@ -85,23 +87,21 @@ static int add_ae_conn(enum ae_id id,
qosspec_t qs,
struct conn_info * rcv_info)
{
- struct ae_conn * ae_conn;
+ struct conn_el * el;
- ae_conn = malloc(sizeof(*ae_conn));
- if (ae_conn == NULL) {
+ el = malloc(sizeof(*el));
+ if (el == NULL) {
log_err("Not enough memory.");
return -1;
}
- ae_conn->conn.conn_info = *rcv_info;
- ae_conn->conn.flow_info.fd = fd;
- ae_conn->conn.flow_info.qs = qs;
-
- list_head_init(&ae_conn->next);
+ el->conn.conn_info = *rcv_info;
+ el->conn.flow_info.fd = fd;
+ el->conn.flow_info.qs = qs;
pthread_mutex_lock(&connmgr.aes[id].lock);
- list_add(&ae_conn->next, &connmgr.aes[id].conns);
+ list_add(&el->next, &connmgr.aes[id].pending);
pthread_cond_signal(&connmgr.aes[id].cond);
pthread_mutex_unlock(&connmgr.aes[id].lock);
@@ -217,6 +217,7 @@ int connmgr_ae_init(enum ae_id id,
}
list_head_init(&ae->conns);
+ list_head_init(&ae->pending);
memcpy(&connmgr.aes[id].info, info, sizeof(connmgr.aes[id].info));
@@ -241,7 +242,13 @@ void connmgr_ae_fini(enum ae_id id)
pthread_mutex_lock(&ae->lock);
list_for_each_safe(p, h, &ae->conns) {
- struct ae_conn * e = list_entry(p, struct ae_conn, next);
+ struct conn_el * e = list_entry(p, struct conn_el, next);
+ list_del(&e->next);
+ free(e);
+ }
+
+ list_for_each_safe(p, h, &ae->pending) {
+ struct conn_el * e = list_entry(p, struct conn_el, next);
list_del(&e->next);
free(e);
}
@@ -256,6 +263,84 @@ void connmgr_ae_fini(enum ae_id id)
connmgr.aes[id].nbs = NULL;
}
+int connmgr_ipcp_connect(const char * dst,
+ const char * component)
+{
+ struct conn_el * ce;
+ int id;
+
+ assert(dst);
+ assert(component);
+
+ ce = malloc(sizeof(*ce));
+ if (ce == NULL) {
+ log_dbg("Out of memory.");
+ return -1;
+ }
+
+ id = get_id_by_name(component);
+ if (id < 0) {
+ log_dbg("No such component: %s", component);
+ free(ce);
+ return -1;
+ }
+
+ /* FIXME: get the correct qos for the component. */
+ if (connmgr_alloc(id, dst, NULL, &ce->conn)) {
+ free(ce);
+ return -1;
+ }
+
+ if (strlen(dst) > DST_MAX_STRLEN) {
+ log_warn("Truncating dst length for connection.");
+ memcpy(ce->conn.flow_info.dst, dst, DST_MAX_STRLEN);
+ ce->conn.flow_info.dst[DST_MAX_STRLEN] = '\0';
+ } else {
+ strcpy(ce->conn.flow_info.dst, dst);
+ }
+
+ pthread_mutex_lock(&connmgr.aes[id].lock);
+
+ list_add(&ce->next, &connmgr.aes[id].conns);
+
+ pthread_mutex_unlock(&connmgr.aes[id].lock);
+
+ return 0;
+}
+
+int connmgr_ipcp_disconnect(const char * dst,
+ const char * component)
+{
+ struct list_head * p;
+ struct list_head * h;
+ int id;
+
+ assert(dst);
+ assert(component);
+
+ id = get_id_by_name(component);
+ if (id < 0)
+ return -1;
+
+ pthread_mutex_lock(&connmgr.aes[id].lock);
+
+ list_for_each_safe(p,h, &connmgr.aes[id].conns) {
+ struct conn_el * el = list_entry(p, struct conn_el, next);
+ if (strcmp(el->conn.flow_info.dst, dst) == 0) {
+ int ret;
+ pthread_mutex_unlock(&connmgr.aes[id].lock);
+ list_del(&el->next);
+ ret = connmgr_dealloc(id, &el->conn);
+ free(el);
+ return ret;
+ }
+ }
+
+ pthread_mutex_unlock(&connmgr.aes[id].lock);
+
+ return 0;
+}
+
int connmgr_alloc(enum ae_id id,
const char * dst,
qosspec_t * qs,
@@ -329,7 +414,7 @@ int connmgr_dealloc(enum ae_id id,
int connmgr_wait(enum ae_id id,
struct conn * conn)
{
- struct ae_conn * ae_conn;
+ struct conn_el * el;
struct ae * ae;
assert(id >= 0 && id < AEID_MAX);
@@ -342,21 +427,21 @@ int connmgr_wait(enum ae_id id,
pthread_cleanup_push((void(*)(void *))pthread_mutex_unlock,
(void *) &ae->lock);
- while (list_is_empty(&ae->conns))
+ while (list_is_empty(&ae->pending))
pthread_cond_wait(&ae->cond, &ae->lock);
pthread_cleanup_pop(false);
- ae_conn = list_first_entry((&ae->conns), struct ae_conn, next);
- if (ae_conn == NULL) {
+ el = list_first_entry((&ae->pending), struct conn_el, next);
+ if (el == NULL) {
pthread_mutex_unlock(&ae->lock);
return -1;
}
- *conn = ae_conn->conn;
+ *conn = el->conn;
- list_del(&ae_conn->next);
- free(ae_conn);
+ list_del(&el->next);
+ free(el);
pthread_mutex_unlock(&ae->lock);
diff --git a/src/ipcpd/normal/connmgr.h b/src/ipcpd/normal/connmgr.h
index 920058da..379877e6 100644
--- a/src/ipcpd/normal/connmgr.h
+++ b/src/ipcpd/normal/connmgr.h
@@ -43,6 +43,12 @@ int connmgr_ae_init(enum ae_id id,
void connmgr_ae_fini(enum ae_id id);
+int connmgr_ipcp_connect(const char * dst,
+ const char * component);
+
+int connmgr_ipcp_disconnect(const char * dst,
+ const char * component);
+
int connmgr_alloc(enum ae_id id,
const char * dst,
qosspec_t * qs,
diff --git a/src/ipcpd/normal/dt.c b/src/ipcpd/normal/dt.c
index 19c2d3a6..aa089852 100644
--- a/src/ipcpd/normal/dt.c
+++ b/src/ipcpd/normal/dt.c
@@ -67,7 +67,6 @@ struct {
pthread_rwlock_t lock;
struct nbs * nbs;
- struct ae * ae;
struct nb_notifier nb_notifier;
@@ -163,6 +162,8 @@ static void * dt_conn_handle(void * o)
log_dbg("Got new connection.");
+ /* NOTE: connection acceptance policy could be here. */
+
nbs_add(dt.nbs, conn);
}
diff --git a/src/ipcpd/normal/enroll.c b/src/ipcpd/normal/enroll.c
index 2f7dd9bc..7f93ed3a 100644
--- a/src/ipcpd/normal/enroll.c
+++ b/src/ipcpd/normal/enroll.c
@@ -259,14 +259,17 @@ static void * enroll_handle(void * o)
continue;
}
- if (msg->code != ENROLL_CODE__ENROLL_DONE) {
+ if (msg->code != ENROLL_CODE__ENROLL_DONE || !msg->has_result) {
log_err("Wrong message type.");
enroll_msg__free_unpacked(msg, NULL);
connmgr_dealloc(AEID_ENROLL, &conn);
continue;
}
- log_dbg("Neighbor enrollment successful.");
+ if (msg->result == 0)
+ log_dbg("Neighbor enrollment successful.");
+ else
+ log_dbg("Neigbor reported failed enrollment.");
connmgr_dealloc(AEID_ENROLL, &conn);
}
@@ -287,13 +290,16 @@ int enroll_boot(struct conn * conn,
return 0;
}
-int enroll_done(struct conn * conn)
+int enroll_done(struct conn * conn,
+ int result)
{
enroll_msg_t msg = ENROLL_MSG__INIT;
uint8_t buf[ENROLL_BUF_LEN];
ssize_t len;
- msg.code = ENROLL_CODE__ENROLL_DONE;
+ msg.code = ENROLL_CODE__ENROLL_DONE;
+ msg.has_result = true;
+ msg.result = result;
len = enroll_msg__get_packed_size(&msg);
if (len < 0) {
diff --git a/src/ipcpd/normal/enroll.h b/src/ipcpd/normal/enroll.h
index 67c9912d..3b277e44 100644
--- a/src/ipcpd/normal/enroll.h
+++ b/src/ipcpd/normal/enroll.h
@@ -40,7 +40,8 @@ void enroll_bootstrap(const struct ipcp_config * conf);
int enroll_boot(struct conn * conn,
const char * dst);
-int enroll_done(struct conn * conn);
+int enroll_done(struct conn * conn,
+ int result);
struct ipcp_config * enroll_get_conf(void);
diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c
index d9fbc2dd..bef04b7a 100644
--- a/src/ipcpd/normal/main.c
+++ b/src/ipcpd/normal/main.c
@@ -263,11 +263,12 @@ static int normal_ipcp_enroll(const char * dst,
}
if (enroll_components(dt_conn.conn_info.addr)) {
+ enroll_done(&er_conn, -1);
log_err("Failed to enroll components.");
goto fail_enroll_comp;
}
- if (enroll_done(&er_conn))
+ if (enroll_done(&er_conn, 0))
log_warn("Failed to confirm enrollment with peer.");
if (connmgr_dealloc(AEID_DT, &dt_conn))
@@ -346,6 +347,8 @@ static int normal_ipcp_query(const uint8_t * dst)
static struct ipcp_ops normal_ops = {
.ipcp_bootstrap = normal_ipcp_bootstrap,
.ipcp_enroll = normal_ipcp_enroll,
+ .ipcp_connect = connmgr_ipcp_connect,
+ .ipcp_disconnect = connmgr_ipcp_disconnect,
.ipcp_reg = dir_reg,
.ipcp_unreg = dir_unreg,
.ipcp_query = normal_ipcp_query,