summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDimitri Staessens <[email protected]>2017-11-08 19:25:48 +0100
committerSander Vrijders <[email protected]>2017-11-08 21:40:28 +0100
commit35c43358a110758090b48dd18628bb285ffddfc6 (patch)
tree9746475ac579e516e86f720a3bcb107bf6e36784 /src
parentc59053040ce927f2926e5a569b19bdd129c354a7 (diff)
downloadouroboros-35c43358a110758090b48dd18628bb285ffddfc6.tar.gz
ouroboros-35c43358a110758090b48dd18628bb285ffddfc6.zip
lib: Use packed struct for FRCT header access
This replaces the variable FRCT header with a packed struct, which significantly simplifies the implementation. The shm_du_buff calls to release the head/tail are updated to return a pointer to the original head or the new tail (in symmetry to the alloc calls, which return a pointer to the new head and old tail), so that it immediately points to the structure that is needed. The frct_pci sources are removed and frct is now fully in the frct.c source file. Signed-off-by: Dimitri Staessens <[email protected]> Signed-off-by: Sander Vrijders <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/lib/CMakeLists.txt1
-rw-r--r--src/lib/dev.c3
-rw-r--r--src/lib/frct.c177
-rw-r--r--src/lib/frct_pci.c129
-rw-r--r--src/lib/frct_pci.h67
-rw-r--r--src/lib/shm_rdrbuff.c22
6 files changed, 140 insertions, 259 deletions
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index ba670acf..3531ac27 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -174,7 +174,6 @@ set(SOURCE_FILES_DEV
# Add source files here
cacep.c
dev.c
- frct_pci.c
timerwheel.c
)
diff --git a/src/lib/dev.c b/src/lib/dev.c
index ff22cca6..e80bf9f9 100644
--- a/src/lib/dev.c
+++ b/src/lib/dev.c
@@ -24,6 +24,7 @@
#include "config.h"
+#include <ouroboros/hash.h>
#include <ouroboros/errno.h>
#include <ouroboros/dev.h>
#include <ouroboros/ipcp-dev.h>
@@ -31,6 +32,7 @@
#include <ouroboros/sockets.h>
#include <ouroboros/fccntl.h>
#include <ouroboros/bitmap.h>
+#include <ouroboros/random.h>
#include <ouroboros/shm_flow_set.h>
#include <ouroboros/shm_rdrbuff.h>
#include <ouroboros/shm_rbuff.h>
@@ -39,7 +41,6 @@
#include <ouroboros/qoscube.h>
#include <ouroboros/timerwheel.h>
-#include "frct_pci.h"
#include "rq.h"
#include <stdlib.h>
diff --git a/src/lib/frct.c b/src/lib/frct.c
index abebb2ff..5f45f522 100644
--- a/src/lib/frct.c
+++ b/src/lib/frct.c
@@ -30,16 +30,20 @@
#define TW_ELEMENTS 6000
#define TW_RESOLUTION 1 /* ms */
+#define FRCT_PCILEN (sizeof(struct frct_pci))
+#define FRCT_CRCLEN (sizeof(uint32_t))
+
struct frct_cr {
- bool drf;
- uint64_t lwe;
- uint64_t rwe;
+ bool drf;
+ uint32_t lwe;
+ uint32_t rwe;
- bool conf;
- uint16_t cflags;
+ uint32_t seqno;
+ bool conf;
+ uint8_t cflags;
- time_t act;
- time_t inact;
+ time_t act;
+ time_t inact;
};
struct frcti {
@@ -63,6 +67,28 @@ struct {
struct timerwheel * tw;
} frct;
+enum frct_flags {
+ FRCT_DATA = 0x01, /* PDU carries data */
+ FRCT_DRF = 0x02, /* Data run flag */
+ FRCT_ACK = 0x03, /* ACK field valid */
+ FRCT_FC = 0x08, /* FC window valid */
+ FRCT_RDVZ = 0x10, /* Rendez-vous */
+ FRCT_CFG = 0x20, /* Configuration */
+ FRCT_MFGM = 0x40, /* More fragments */
+ FRCT_CRC = 0x80, /* CRC present */
+};
+
+struct frct_pci {
+ uint8_t flags;
+
+ uint8_t cflags;
+
+ uint16_t window;
+
+ uint32_t seqno;
+ uint32_t ackno;
+} __attribute__((packed));
+
static int frct_init(void)
{
frct.tw = timerwheel_create(TW_RESOLUTION, TW_RESOLUTION * TW_ELEMENTS);
@@ -104,6 +130,11 @@ static struct frcti * frcti_create(int fd)
frcti->snd_cr.drf = true;
frcti->snd_cr.conf = true;
+#ifdef OUROBOROS_CONFIG_DEBUG
+ frcti->snd_cr.seqno = 0;
+#else
+ random_buffer(&frcti->snd_cr.seqno, sizeof(frcti->snd_cr.seqno));
+#endif
frcti->snd_cr.lwe = 0;
frcti->snd_cr.rwe = 0;
frcti->snd_cr.cflags = 0;
@@ -201,44 +232,79 @@ static ssize_t __frcti_queued_pdu(struct frcti * frcti)
return idx;
}
+static int frct_chk_crc(uint8_t * head,
+ uint8_t * tail)
+{
+ uint32_t crc;
+
+ mem_hash(HASH_CRC32, &crc, head, tail - head);
+
+ return crc == *((uint32_t *) tail);
+}
+
+static void frct_add_crc(uint8_t * head,
+ uint8_t * tail)
+{
+ mem_hash(HASH_CRC32, tail, head, tail - head);
+}
+
+static struct frct_pci * frcti_alloc_head(struct shm_du_buff * sdb)
+{
+ struct frct_pci * pci = NULL;
+
+ pci = (struct frct_pci *) shm_du_buff_head_alloc(sdb, FRCT_PCILEN);
+ if (pci != NULL)
+ memset(pci, 0, sizeof(*pci));
+
+ return pci;
+}
+
static int __frcti_snd(struct frcti * frcti,
struct shm_du_buff * sdb)
{
- struct frct_pci pci;
- struct timespec now;
- struct frct_cr * snd_cr;
+ struct frct_pci * pci;
+ struct timespec now;
+ struct frct_cr * snd_cr;
- if (frcti == NULL)
- return 0;
+ assert(frcti);
snd_cr = &frcti->snd_cr;
- memset(&pci, 0, sizeof(pci));
+ pci = frcti_alloc_head(sdb);
+ if (pci == NULL)
+ return -1;
clock_gettime(CLOCK_REALTIME_COARSE, &now);
- pci.type |= PDU_TYPE_DATA;
-
pthread_rwlock_wrlock(&frcti->lock);
/* Check if sender is inactive. */
if (!snd_cr->drf && now.tv_sec - snd_cr->act > snd_cr->inact)
snd_cr->drf = true;
+ pci->flags |= FRCT_DATA;
+
/* Set the DRF in the first packet of a new run of SDUs. */
if (snd_cr->drf) {
- pci.flags |= FLAG_DATA_RUN;
+ pci->flags |= FRCT_DRF;
if (snd_cr->conf) {
- pci.type |= PDU_TYPE_CONFIG;
- pci.cflags = snd_cr->cflags;
+ pci->flags |= FRCT_CFG;
+ pci->cflags = snd_cr->cflags;
}
}
- pci.seqno = snd_cr->lwe++;
+ pci->seqno = snd_cr->seqno++;
- if (frct_pci_ser(sdb, &pci, snd_cr->cflags & FRCTFERRCHCK)) {
- pthread_rwlock_unlock(&frcti->lock);
- return -1;
+ if (snd_cr->cflags & FRCTFERRCHCK) {
+ uint8_t * tail = shm_du_buff_tail_alloc(sdb, FRCT_CRCLEN);
+ if (tail == NULL) {
+ pthread_rwlock_unlock(&frcti->lock);
+ return -1;
+ }
+
+ frct_add_crc((uint8_t *) pci, tail);
+
+ pci->flags |= FRCT_CRC;
}
snd_cr->act = now.tv_sec;
@@ -255,44 +321,55 @@ static int __frcti_snd(struct frcti * frcti,
static int __frcti_rcv(struct frcti * frcti,
struct shm_du_buff * sdb)
{
- ssize_t idx;
- struct frct_pci pci;
- struct timespec now;
- struct frct_cr * rcv_cr;
+ ssize_t idx;
+ struct frct_pci * pci;
+ struct timespec now;
+ struct frct_cr * rcv_cr;
assert(frcti);
rcv_cr = &frcti->rcv_cr;
+ pci = (struct frct_pci *) shm_du_buff_head_release(sdb, FRCT_PCILEN);
+
clock_gettime(CLOCK_REALTIME_COARSE, &now);
pthread_rwlock_wrlock(&frcti->lock);
idx = shm_du_buff_get_idx(sdb);
- /* SDU may be corrupted. */
- if (frct_pci_des(sdb, &pci, rcv_cr->cflags & FRCTFERRCHCK)) {
- pthread_rwlock_unlock(&frcti->lock);
- shm_rdrbuff_remove(ai.rdrb, idx);
- return -EAGAIN;
+ /* PDU may be corrupted. */
+ if (pci->flags & FRCT_CRC) {
+ uint8_t * tail = shm_du_buff_tail_release(sdb, FRCT_CRCLEN);
+ if (frct_chk_crc((uint8_t *) pci, tail))
+ goto fail_clean;
}
/* Check if receiver inactivity is true. */
if (!rcv_cr->drf && now.tv_sec - rcv_cr->act > rcv_cr->inact)
rcv_cr->drf = true;
- /* When there is receiver inactivity and no DRF, drop the SDU. */
- if (rcv_cr->drf && !(pci.flags & FLAG_DATA_RUN)) {
- pthread_rwlock_unlock(&frcti->lock);
- shm_rdrbuff_remove(ai.rdrb, idx);
- return -EAGAIN;
+ /* When there is receiver inactivity and no DRF, drop the PDU. */
+ if (rcv_cr->drf && !(pci->flags & FRCT_DRF))
+ goto fail_clean;
+
+ /* Queue the PDU if needed. */
+ if (rcv_cr->cflags & FRCTFORDERING) {
+ if (pci->seqno != frcti->rcv_cr.lwe) {
+ /* NOTE: queued PDUs head/tail without PCI. */
+ if (rq_push(frcti->rq, pci->seqno, idx))
+ shm_rdrbuff_remove(ai.rdrb, idx);
+ goto fail;
+ } else {
+ ++rcv_cr->lwe;
+ }
}
/* If the DRF is set, reset the state of the connection. */
- if (pci.flags & FLAG_DATA_RUN) {
- rcv_cr->lwe = pci.seqno;
- if (pci.type & PDU_TYPE_CONFIG)
- rcv_cr->cflags = pci.cflags;
+ if (pci->flags & FRCT_DRF) {
+ rcv_cr->lwe = pci->seqno;
+ if (pci->flags & FRCT_CFG)
+ rcv_cr->cflags = pci->cflags;
}
if (rcv_cr->drf)
@@ -300,21 +377,17 @@ static int __frcti_rcv(struct frcti * frcti,
rcv_cr->act = now.tv_sec;
- if (!(pci.type & PDU_TYPE_DATA))
+ if (!(pci->flags & FRCT_DATA))
shm_rdrbuff_remove(ai.rdrb, idx);
- if (rcv_cr->cflags & FRCTFORDERING) {
- if (pci.seqno != frcti->rcv_cr.lwe) {
- if (rq_push(frcti->rq, pci.seqno, idx))
- shm_rdrbuff_remove(ai.rdrb, idx);
- pthread_rwlock_unlock(&frcti->lock);
- return -EAGAIN;
- } else {
- ++rcv_cr->lwe;
- }
- }
-
pthread_rwlock_unlock(&frcti->lock);
return 0;
+
+ fail_clean:
+ if (!(pci->flags & FRCT_DATA))
+ shm_rdrbuff_remove(ai.rdrb, idx);
+ fail:
+ pthread_rwlock_unlock(&frcti->lock);
+ return -EAGAIN;
}
diff --git a/src/lib/frct_pci.c b/src/lib/frct_pci.c
deleted file mode 100644
index 509cc8e2..00000000
--- a/src/lib/frct_pci.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Ouroboros - Copyright (C) 2016 - 2017
- *
- * Protocol Control Information of FRCT
- *
- * Dimitri Staessens <[email protected]>
- * Sander Vrijders <[email protected]>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., http://www.fsf.org/about/contact/.
- */
-
-#include <ouroboros/hash.h>
-#include <ouroboros/errno.h>
-
-#include "frct_pci.h"
-
-#include <assert.h>
-#include <string.h>
-
-#define TYPE_SIZE 1
-#define FLAGS_SIZE 1
-#define SEQNO_SIZE 8
-#define CONF_FLAGS_SIZE 2
-
-#define BASE_SIZE TYPE_SIZE + FLAGS_SIZE + SEQNO_SIZE
-
-#define head_len(pci) (pci->type & PDU_TYPE_CONFIG ? \
- BASE_SIZE + CONF_FLAGS_SIZE : BASE_SIZE)
-
-int frct_pci_ser(struct shm_du_buff * sdb,
- struct frct_pci * pci,
- bool error_check)
-{
- uint8_t * head;
- uint8_t * tail;
- size_t offset = 0;
-
- assert(sdb);
- assert(pci);
-
- head = shm_du_buff_head_alloc(sdb, head_len(pci));
- if (head == NULL)
- return -EPERM;
-
- memcpy(head, &pci->type, TYPE_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->cflags, 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_len(pci));
- return -EPERM;
- }
-
- *((uint32_t *) tail) = 0;
- mem_hash(HASH_CRC32, (uint32_t *) tail, head, tail - head);
- }
-
- return 0;
-}
-
-int frct_pci_des(struct shm_du_buff * sdb,
- struct frct_pci * pci,
- bool error_check)
-{
- uint8_t * head;
- uint8_t * tail;
- uint32_t crc;
- uint32_t crc2;
- size_t offset = 0;
-
- assert(sdb);
- assert(pci);
-
- head = shm_du_buff_head(sdb);
-
- if (error_check) {
- tail = shm_du_buff_tail(sdb);
-
- mem_hash(HASH_CRC32, &crc, head,
- tail - head - hash_len(HASH_CRC32));
-
- memcpy(&crc2, tail - hash_len(HASH_CRC32),
- hash_len(HASH_CRC32));
-
- /* Corrupted SDU. */
- if (crc != crc2)
- return -1;
-
- shm_du_buff_tail_release(sdb, hash_len(HASH_CRC32));
- }
-
- /* Depending on the type a different deserialization. */
- memcpy(&pci->type, head, TYPE_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->cflags, head + offset, CONF_FLAGS_SIZE);
- /* offset += CONF_FLAGS_SIZE; */
- }
-
- shm_du_buff_head_release(sdb, head_len(pci));
-
- return 0;
-}
diff --git a/src/lib/frct_pci.h b/src/lib/frct_pci.h
deleted file mode 100644
index fbbfd354..00000000
--- a/src/lib/frct_pci.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Ouroboros - Copyright (C) 2016 - 2017
- *
- * Protocol Control Information of FRCT
- *
- * Dimitri Staessens <[email protected]>
- * Sander Vrijders <[email protected]>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * version 2.1 as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., http://www.fsf.org/about/contact/.
- */
-
-#ifndef OUROBOROS_LIB_FRCT_PCI_H
-#define OUROBOROS_LIB_FRCT_PCI_H
-
-#include <ouroboros/shm_du_buff.h>
-
-#include <stdint.h>
-#include <stdbool.h>
-
-struct frct_pci {
- /* Present in every PDU. */
- uint8_t type;
- uint8_t flags;
- uint64_t seqno;
-
- /* Present in config PDU. */
- uint16_t cflags;
-
- /* Present in flow control PDU. */
- uint64_t lwe;
- uint64_t rwe;
-};
-
-enum pdu_types {
- PDU_TYPE_DATA = 0x01,
- PDU_TYPE_ACK = 0x02,
- PDU_TYPE_FC = 0x04,
- PDU_TYPE_ACK_AND_FC = (PDU_TYPE_ACK | PDU_TYPE_FC),
- PDU_TYPE_RENDEZ_VOUS = 0x08,
- PDU_TYPE_CONFIG = 0x10
-};
-
-enum data_flags {
- FLAG_DATA_RUN = 0x01,
- FLAG_MORE_FRAGMENTS = 0x02
-};
-
-int frct_pci_ser(struct shm_du_buff * sdb,
- struct frct_pci * pci,
- bool error_check);
-
-int frct_pci_des(struct shm_du_buff * sdb,
- struct frct_pci * pci,
- bool error_check);
-
-#endif /* OUROBOROS_LIB_FRCT_PCI_H */
diff --git a/src/lib/shm_rdrbuff.c b/src/lib/shm_rdrbuff.c
index a3333a35..2853d5bb 100644
--- a/src/lib/shm_rdrbuff.c
+++ b/src/lib/shm_rdrbuff.c
@@ -602,8 +602,6 @@ uint8_t * shm_du_buff_tail(struct shm_du_buff * sdb)
uint8_t * shm_du_buff_head_alloc(struct shm_du_buff * sdb,
size_t size)
{
- uint8_t * buf = NULL;
-
assert(sdb);
if (sdb->du_head < size)
@@ -611,15 +609,13 @@ uint8_t * shm_du_buff_head_alloc(struct shm_du_buff * sdb,
sdb->du_head -= size;
- buf = (uint8_t *) (sdb + 1) + sdb->du_head;
-
- return buf;
+ return (uint8_t *) (sdb + 1) + sdb->du_head;
}
uint8_t * shm_du_buff_tail_alloc(struct shm_du_buff * sdb,
size_t size)
{
- uint8_t * buf = NULL;
+ uint8_t * buf;
assert(sdb);
@@ -633,22 +629,30 @@ uint8_t * shm_du_buff_tail_alloc(struct shm_du_buff * sdb,
return buf;
}
-void shm_du_buff_head_release(struct shm_du_buff * sdb,
- size_t size)
+uint8_t * shm_du_buff_head_release(struct shm_du_buff * sdb,
+ size_t size)
{
+ uint8_t * buf;
+
assert(sdb);
assert(!(size > sdb->du_tail - sdb->du_head));
+ buf = (uint8_t *) (sdb + 1) + sdb->du_head;
+
sdb->du_head += size;
+
+ return buf;
}
-void shm_du_buff_tail_release(struct shm_du_buff * sdb,
+uint8_t * shm_du_buff_tail_release(struct shm_du_buff * sdb,
size_t size)
{
assert(sdb);
assert(!(size > sdb->du_tail - sdb->du_head));
sdb->du_tail -= size;
+
+ return (uint8_t *) (sdb + 1) + sdb->du_tail;
}
void shm_du_buff_truncate(struct shm_du_buff * sdb,