diff options
-rw-r--r-- | include/ouroboros/frct_pci.h | 6 | ||||
-rw-r--r-- | src/lib/dev.c | 206 | ||||
-rw-r--r-- | src/lib/frct_pci.c | 62 |
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; } |