From 35c43358a110758090b48dd18628bb285ffddfc6 Mon Sep 17 00:00:00 2001 From: Dimitri Staessens Date: Wed, 8 Nov 2017 19:25:48 +0100 Subject: 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 Signed-off-by: Sander Vrijders --- include/ouroboros/shm_du_buff.h | 4 +- src/lib/CMakeLists.txt | 1 - src/lib/dev.c | 3 +- src/lib/frct.c | 177 ++++++++++++++++++++++++++++------------ src/lib/frct_pci.c | 129 ----------------------------- src/lib/frct_pci.h | 67 --------------- src/lib/shm_rdrbuff.c | 22 +++-- 7 files changed, 142 insertions(+), 261 deletions(-) delete mode 100644 src/lib/frct_pci.c delete mode 100644 src/lib/frct_pci.h diff --git a/include/ouroboros/shm_du_buff.h b/include/ouroboros/shm_du_buff.h index c558f378..04e17cf4 100644 --- a/include/ouroboros/shm_du_buff.h +++ b/include/ouroboros/shm_du_buff.h @@ -40,10 +40,10 @@ uint8_t * shm_du_buff_head_alloc(struct shm_du_buff * sdb, uint8_t * shm_du_buff_tail_alloc(struct shm_du_buff * sdb, size_t size); -void shm_du_buff_head_release(struct shm_du_buff * sdb, +uint8_t * shm_du_buff_head_release(struct shm_du_buff * sdb, size_t size); -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); void shm_du_buff_truncate(struct shm_du_buff * sdb, 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 #include #include #include @@ -31,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +41,6 @@ #include #include -#include "frct_pci.h" #include "rq.h" #include 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 - * Sander Vrijders - * - * 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 -#include - -#include "frct_pci.h" - -#include -#include - -#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 - * Sander Vrijders - * - * 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 - -#include -#include - -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, -- cgit v1.2.3