summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ouroboros/frct_pci.h6
-rw-r--r--src/lib/dev.c206
-rw-r--r--src/lib/frct_pci.c62
3 files changed, 179 insertions, 95 deletions
diff --git a/include/ouroboros/frct_pci.h b/include/ouroboros/frct_pci.h
index 3a93ac1c..601c0ce4 100644
--- a/include/ouroboros/frct_pci.h
+++ b/include/ouroboros/frct_pci.h
@@ -29,9 +29,15 @@
#include <stdbool.h>
struct frct_pci {
+ /* Present in every PDU. */
uint8_t type;
uint8_t flags;
uint64_t seqno;
+
+ /* Present in config PDU. */
+ uint8_t conf_flags;
+
+ /* Present in flow control PDU. */
uint64_t lwe;
uint64_t rwe;
};
diff --git a/src/lib/dev.c b/src/lib/dev.c
index 6e85aaad..cfcfdf81 100644
--- a/src/lib/dev.c
+++ b/src/lib/dev.c
@@ -60,7 +60,7 @@ struct flow_set {
};
struct fqueue {
- int fqueue[SHM_BUFFER_SIZE]; /* safe copy from shm */
+ int fqueue[SHM_BUFFER_SIZE]; /* Safe copy from shm. */
size_t fqsize;
size_t next;
};
@@ -236,7 +236,7 @@ static int api_announce(char * ap_name)
return ret;
}
-/* Call under flows lock */
+/* Call under flows lock. */
static int finalize_write(int fd,
size_t idx)
{
@@ -264,8 +264,6 @@ static int frcti_init(int fd)
frcti->rcv_lwe = 0;
frcti->rcv_rwe = 0;
- frcti->conf_flags = CONF_ERROR_CHECK;
-
return 0;
}
@@ -284,25 +282,12 @@ static void frcti_fini(int fd)
frcti_clear(fd);
}
-static int frcti_configure(int fd,
- qosspec_t * qos)
+static int frcti_send(int fd,
+ struct frct_pci * pci,
+ struct shm_du_buff * sdb)
{
- /* FIXME: Send configuration message here to other side. */
-
- (void) fd;
- (void) qos;
-
- return 0;
-}
-
-static int frcti_write(int fd,
- struct shm_du_buff * sdb)
-{
- struct frcti * frcti;
- struct frct_pci pci;
struct timespec now = {0, 0};
-
- memset(&pci, 0, sizeof(pci));
+ struct frcti * frcti;
frcti = &(ai.frcti[fd]);
@@ -316,16 +301,15 @@ static int frcti_write(int fd,
/* Set the DRF in the first packet of a new run of SDUs. */
if (frcti->snd_drf) {
- pci.flags |= FLAG_DATA_RUN;
+ pci->flags |= FLAG_DATA_RUN;
frcti->snd_drf = false;
}
frcti->last_snd = now;
- pci.seqno = frcti->snd_lwe++;
- pci.type |= PDU_TYPE_DATA;
+ pci->seqno = frcti->snd_lwe++;
- if (frct_pci_ser(sdb, &pci, frcti->conf_flags & CONF_ERROR_CHECK)) {
+ if (frct_pci_ser(sdb, pci, frcti->conf_flags & CONF_ERROR_CHECK)) {
pthread_rwlock_unlock(&ai.lock);
return -1;
}
@@ -340,6 +324,65 @@ static int frcti_write(int fd,
return 0;
}
+
+static int frcti_configure(int fd,
+ qosspec_t * qos)
+{
+ struct frcti * frcti;
+ struct frct_pci pci;
+ struct shm_du_buff * sdb;
+
+ frcti = &(ai.frcti[fd]);
+
+ memset(&pci, 0, sizeof(pci));
+
+ if (qos == NULL)
+ return 0;
+
+ if (ipcp_sdb_reserve(&sdb, 0))
+ return -1;
+
+ if (qos->resource_control)
+ pci.conf_flags |= CONF_RESOURCE_CONTROL;
+ if (qos->reliable)
+ pci.conf_flags |= CONF_RELIABLE;
+ if (qos->error_check)
+ pci.conf_flags |= CONF_ERROR_CHECK;
+ if (qos->ordered)
+ pci.conf_flags |= CONF_ORDERED;
+ if (qos->partial)
+ pci.conf_flags |= CONF_PARTIAL;
+
+ /* Always set the DRF on a configure message. */
+ pci.flags |= FLAG_DATA_RUN;
+ pci.type |= PDU_TYPE_CONFIG;
+
+ pthread_rwlock_wrlock(&ai.lock);
+
+ frcti->conf_flags = pci.conf_flags;
+
+ pthread_rwlock_unlock(&ai.lock);
+
+ if (frcti_send(fd, &pci, sdb)) {
+ shm_rdrbuff_remove(ai.rdrb, shm_du_buff_get_idx(sdb));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int frcti_write(int fd,
+ struct shm_du_buff * sdb)
+{
+ struct frct_pci pci;
+
+ memset(&pci, 0, sizeof(pci));
+
+ pci.type |= PDU_TYPE_DATA;
+
+ return frcti_send(fd, &pci, sdb);
+}
+
static ssize_t frcti_read(int fd)
{
ssize_t idx = -1;
@@ -349,69 +392,77 @@ static ssize_t frcti_read(int fd)
struct shm_du_buff * sdb;
struct timespec now = {0, 0};
- pthread_rwlock_rdlock(&ai.lock);
+ do {
+ pthread_rwlock_rdlock(&ai.lock);
- if (ai.flows[fd].oflags & FLOW_O_NONBLOCK) {
- idx = shm_rbuff_read(ai.flows[fd].rx_rb);
- pthread_rwlock_unlock(&ai.lock);
- } else {
- struct shm_rbuff * rb = ai.flows[fd].rx_rb;
- bool timeo = ai.flows[fd].timesout;
- struct timespec timeout = ai.flows[fd].rcv_timeo;
+ if (ai.flows[fd].oflags & FLOW_O_NONBLOCK) {
+ idx = shm_rbuff_read(ai.flows[fd].rx_rb);
+ pthread_rwlock_unlock(&ai.lock);
+ } else {
+ struct shm_rbuff * rb = ai.flows[fd].rx_rb;
+ bool timeo = ai.flows[fd].timesout;
+ struct timespec timeout = ai.flows[fd].rcv_timeo;
- pthread_rwlock_unlock(&ai.lock);
+ pthread_rwlock_unlock(&ai.lock);
- if (timeo) {
- clock_gettime(PTHREAD_COND_CLOCK, &abstime);
- ts_add(&abstime, &timeout, &abstime);
- idx = shm_rbuff_read_b(rb, &abstime);
- } else {
- idx = shm_rbuff_read_b(rb, NULL);
+ if (timeo) {
+ clock_gettime(PTHREAD_COND_CLOCK, &abstime);
+ ts_add(&abstime, &timeout, &abstime);
+ idx = shm_rbuff_read_b(rb, &abstime);
+ } else {
+ idx = shm_rbuff_read_b(rb, NULL);
+ }
}
- }
- if (idx < 0)
- return idx;
+ if (idx < 0)
+ return idx;
- clock_gettime(CLOCK_REALTIME_COARSE, &now);
+ clock_gettime(CLOCK_REALTIME_COARSE, &now);
- pthread_rwlock_wrlock(&ai.lock);
+ pthread_rwlock_wrlock(&ai.lock);
- frcti = &(ai.frcti[fd]);
+ frcti = &(ai.frcti[fd]);
- sdb = shm_rdrbuff_get(ai.rdrb, idx);
+ sdb = shm_rdrbuff_get(ai.rdrb, idx);
- /* SDU may be corrupted. */
- if (frct_pci_des(sdb, &pci, frcti->conf_flags & CONF_ERROR_CHECK)) {
- pthread_rwlock_unlock(&ai.lock);
- shm_rdrbuff_remove(ai.rdrb, idx);
- return -EAGAIN;
- }
+ /* SDU may be corrupted. */
+ if (frct_pci_des(sdb, &pci,
+ frcti->conf_flags & CONF_ERROR_CHECK)) {
+ pthread_rwlock_unlock(&ai.lock);
+ shm_rdrbuff_remove(ai.rdrb, idx);
+ return -EAGAIN;
+ }
- /* Check if receiver inactivity is true. */
- if (!frcti->rcv_drf && ts_diff_ms(&now, &frcti->last_rcv) > 3 * MPL)
- frcti->rcv_drf = true;
+ /* Check if receiver inactivity is true. */
+ if (!frcti->rcv_drf &&
+ ts_diff_ms(&now, &frcti->last_rcv) > 3 * MPL)
+ frcti->rcv_drf = true;
- /* We don't accept packets when there is receiver inactivity. */
- if (frcti->rcv_drf && !(pci.flags & FLAG_DATA_RUN)) {
- pthread_rwlock_unlock(&ai.lock);
- shm_rdrbuff_remove(ai.rdrb, idx);
- return -EAGAIN;
- }
+ /* We don't accept packets when there is receiver inactivity. */
+ if (frcti->rcv_drf && !(pci.flags & FLAG_DATA_RUN)) {
+ pthread_rwlock_unlock(&ai.lock);
+ shm_rdrbuff_remove(ai.rdrb, idx);
+ return -EAGAIN;
+ }
- /*
- * If there is no receiver inactivity and the DRF is set,
- * reset the state of the connection.
- */
- if (pci.flags & FLAG_DATA_RUN)
- frcti->rcv_lwe = pci.seqno;
+ /* If the DRF is set, reset the state of the connection. */
+ if (pci.flags & FLAG_DATA_RUN)
+ frcti->rcv_lwe = pci.seqno;
- if (frcti->rcv_drf)
- frcti->rcv_drf = false;
+ if (pci.type & PDU_TYPE_CONFIG)
+ frcti->conf_flags = pci.conf_flags;
- frcti->last_rcv = now;
+ if (frcti->rcv_drf)
+ frcti->rcv_drf = false;
- pthread_rwlock_unlock(&ai.lock);
+ frcti->last_rcv = now;
+
+ pthread_rwlock_unlock(&ai.lock);
+
+ if (!(pci.type & PDU_TYPE_DATA))
+ shm_rdrbuff_remove(ai.rdrb, idx);
+
+ } while (!(pci.type & PDU_TYPE_DATA));
return idx;
}
@@ -768,15 +819,14 @@ int flow_alloc(const char * dst_name,
frcti_init(fd);
+ pthread_rwlock_unlock(&ai.lock);
+
if (frcti_configure(fd, qs)) {
flow_fini(fd);
bmp_release(ai.fds, fd);
- pthread_rwlock_unlock(&ai.lock);
return -1;
}
- pthread_rwlock_unlock(&ai.lock);
-
return fd;
}
@@ -976,7 +1026,7 @@ ssize_t flow_write(int fd,
return idx;
}
- } else { /* blocking */
+ } else { /* Blocking. */
pthread_rwlock_unlock(&ai.lock);
idx = shm_rdrbuff_write_b(ai.rdrb,
@@ -1052,7 +1102,7 @@ ssize_t flow_read(int fd,
return n;
}
-/* fqueue functions */
+/* fqueue functions. */
struct flow_set * flow_set_create()
{
@@ -1239,7 +1289,7 @@ int flow_event_wait(struct flow_set * set,
return ret;
}
-/* ipcp-dev functions */
+/* ipcp-dev functions. */
int np1_flow_alloc(pid_t n_api,
int port_id,
diff --git a/src/lib/frct_pci.c b/src/lib/frct_pci.c
index 5ee14829..115a3eb9 100644
--- a/src/lib/frct_pci.c
+++ b/src/lib/frct_pci.c
@@ -24,18 +24,25 @@
#include <ouroboros/hash.h>
#include <ouroboros/errno.h>
-#define OUROBOROS_PREFIX "frct-pci"
-#include <ouroboros/logs.h>
-
#include <assert.h>
#include <string.h>
-#define TYPE_SIZE 1
-#define SEQNO_SIZE 8
-#define FLAGS_SIZE 1
+#define TYPE_SIZE 1
+#define SEQNO_SIZE 8
+#define FLAGS_SIZE 1
+#define CONF_FLAGS_SIZE 1
+#define BASE_SIZE TYPE_SIZE + FLAGS_SIZE + SEQNO_SIZE
+#define CONFIG_SIZE CONF_FLAGS_SIZE
+
+static size_t get_head_len(struct frct_pci * pci)
+{
+ size_t len = BASE_SIZE;
+
+ if (pci->type & PDU_TYPE_CONFIG)
+ len += CONFIG_SIZE;
-/* FIXME: Head size will differ on type */
-#define HEAD_SIZE TYPE_SIZE + FLAGS_SIZE + SEQNO_SIZE
+ return len;
+}
int frct_pci_ser(struct shm_du_buff * sdb,
struct frct_pci * pci,
@@ -43,22 +50,34 @@ int frct_pci_ser(struct shm_du_buff * sdb,
{
uint8_t * head;
uint8_t * tail;
+ size_t len;
+ size_t offset = 0;
assert(sdb);
assert(pci);
- head = shm_du_buff_head_alloc(sdb, HEAD_SIZE);
+ len = get_head_len(pci);
+
+ head = shm_du_buff_head_alloc(sdb, len);
if (head == NULL)
return -EPERM;
memcpy(head, &pci->type, TYPE_SIZE);
- memcpy(head + TYPE_SIZE, &pci->flags, FLAGS_SIZE);
- memcpy(head + TYPE_SIZE + FLAGS_SIZE, &pci->seqno, SEQNO_SIZE);
+ offset += TYPE_SIZE;
+ memcpy(head + offset, &pci->flags, FLAGS_SIZE);
+ offset += FLAGS_SIZE;
+ memcpy(head + offset, &pci->seqno, SEQNO_SIZE);
+ offset += SEQNO_SIZE;
+
+ if (pci->type & PDU_TYPE_CONFIG) {
+ memcpy(head + offset, &pci->conf_flags, CONF_FLAGS_SIZE);
+ offset += CONF_FLAGS_SIZE;
+ }
if (error_check) {
tail = shm_du_buff_tail_alloc(sdb, hash_len(HASH_CRC32));
if (tail == NULL) {
- shm_du_buff_head_release(sdb, HEAD_SIZE);
+ shm_du_buff_head_release(sdb, len);
return -EPERM;
}
@@ -77,16 +96,25 @@ int frct_pci_des(struct shm_du_buff * sdb,
uint8_t * tail;
uint32_t crc;
uint32_t crc2;
+ size_t offset = 0;
assert(sdb);
assert(pci);
head = shm_du_buff_head(sdb);
- /* FIXME: Depending on the type a different deserialization */
+ /* Depending on the type a different deserialization. */
memcpy(&pci->type, head, TYPE_SIZE);
- memcpy(&pci->flags, head + TYPE_SIZE, FLAGS_SIZE);
- memcpy(&pci->seqno, head + TYPE_SIZE + FLAGS_SIZE, SEQNO_SIZE);
+ offset += TYPE_SIZE;
+ memcpy(&pci->flags, head + offset, FLAGS_SIZE);
+ offset += FLAGS_SIZE;
+ memcpy(&pci->seqno, head + offset, SEQNO_SIZE);
+ offset += SEQNO_SIZE;
+
+ if (pci->type & PDU_TYPE_CONFIG) {
+ memcpy(&pci->conf_flags, head + offset, CONF_FLAGS_SIZE);
+ offset += CONF_FLAGS_SIZE;
+ }
if (error_check) {
tail = shm_du_buff_tail(sdb);
@@ -99,14 +127,14 @@ int frct_pci_des(struct shm_du_buff * sdb,
memcpy(&crc2, tail - hash_len(HASH_CRC32),
hash_len(HASH_CRC32));
- /* Corrupted SDU */
+ /* Corrupted SDU. */
if (crc != crc2)
return -1;
shm_du_buff_tail_release(sdb, hash_len(HASH_CRC32));
}
- shm_du_buff_head_release(sdb, HEAD_SIZE);
+ shm_du_buff_head_release(sdb, get_head_len(pci));
return 0;
}