/* * Ouroboros - Copyright (C) 2016 - 2017 * * Protocol Control Information in Shared Memory Map * * Dimitri Staessens <dimitri.staessens@ugent.be> * Sander Vrijders <sander.vrijders@ugent.be> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <ouroboros/config.h> #include <ouroboros/errno.h> #include <ouroboros/crc32.h> #include <ouroboros/rib.h> #include "dt_const.h" #include "shm_pci.h" #include "ribconfig.h" #include <stdlib.h> #include <string.h> #include <assert.h> #define PDU_TYPE_SIZE 1 #define QOS_ID_SIZE 1 #define DEFAULT_TTL 60 #define TTL_SIZE 1 #define CHK_SIZE 4 struct { struct dt_const dtc; size_t head_size; size_t tail_size; /* offsets */ size_t dst_addr_o; size_t src_addr_o; size_t dst_cep_id_o; size_t src_cep_id_o; size_t pdu_length_o; size_t seqno_o; size_t qos_id_o; size_t ttl_o; } pci_info; static void ser_pci_head(uint8_t * head, struct pci * pci) { uint8_t ttl = DEFAULT_TTL; assert(head); assert(pci); /* FIXME: Add check and operations for Big Endian machines */ memcpy(head, &pci->pdu_type, PDU_TYPE_SIZE); memcpy(head + pci_info.dst_addr_o, &pci->dst_addr, pci_info.dtc.addr_size); memcpy(head + pci_info.src_addr_o, &pci->src_addr, pci_info.dtc.addr_size); memcpy(head + pci_info.dst_cep_id_o, &pci->dst_cep_id, pci_info.dtc.cep_id_size); memcpy(head + pci_info.src_cep_id_o, &pci->src_cep_id, pci_info.dtc.cep_id_size); memcpy(head + pci_info.pdu_length_o, &pci->pdu_length, pci_info.dtc.pdu_length_size); memcpy(head + pci_info.seqno_o, &pci->seqno, pci_info.dtc.seqno_size); memcpy(head + pci_info.qos_id_o, &pci->qos_id, QOS_ID_SIZE); if (pci_info.dtc.has_ttl) memcpy(head + pci_info.ttl_o, &ttl, TTL_SIZE); } int shm_pci_init(void) { /* read dt constants from the RIB */ if (rib_read(BOOT_PATH "/dt/const/addr_size", &pci_info.dtc.addr_size, sizeof(pci_info.dtc.addr_size)) < 0 || rib_read(BOOT_PATH "/dt/const/cep_id_size", &pci_info.dtc.cep_id_size, sizeof(pci_info.dtc.cep_id_size)) < 0 || rib_read(BOOT_PATH "/dt/const/seqno_size", &pci_info.dtc.seqno_size, sizeof(pci_info.dtc.seqno_size)) < 0 || rib_read(BOOT_PATH "/dt/const/pdu_length_size", &pci_info.dtc.pdu_length_size, sizeof(pci_info.dtc.pdu_length_size)) < 0 || rib_read(BOOT_PATH "/dt/const/has_ttl", &pci_info.dtc.has_ttl, sizeof(pci_info.dtc.has_ttl)) < 0 || rib_read(BOOT_PATH "/dt/const/has_chk", &pci_info.dtc.has_chk, sizeof(pci_info.dtc.has_chk)) < 0 || rib_read(BOOT_PATH "/dt/const/min_pdu_size", &pci_info.dtc.min_pdu_size, sizeof(pci_info.dtc.min_pdu_size)) < 0 || rib_read(BOOT_PATH "/dt/const/max_pdu_size", &pci_info.dtc.max_pdu_size, sizeof(pci_info.dtc.max_pdu_size)) < 0) return -1; pci_info.dst_addr_o = PDU_TYPE_SIZE; pci_info.src_addr_o = pci_info.dst_addr_o + pci_info.dtc.addr_size; pci_info.dst_cep_id_o = pci_info.src_addr_o + pci_info.dtc.addr_size; pci_info.src_cep_id_o = pci_info.dst_cep_id_o + pci_info.dtc.cep_id_size; pci_info.pdu_length_o = pci_info.src_cep_id_o + pci_info.dtc.cep_id_size; pci_info.seqno_o = pci_info.pdu_length_o + pci_info.dtc.pdu_length_size; pci_info.qos_id_o = pci_info.seqno_o + pci_info.dtc.seqno_size; pci_info.ttl_o = pci_info.qos_id_o + QOS_ID_SIZE; pci_info.head_size = pci_info.ttl_o; if (pci_info.dtc.has_ttl) pci_info.head_size += TTL_SIZE; pci_info.tail_size = pci_info.dtc.has_chk ? CHK_SIZE : 0; return 0; } void shm_pci_fini(void) { return; } int shm_pci_ser(struct shm_du_buff * sdb, struct pci * pci) { uint8_t * head; uint8_t * tail; assert(sdb); assert(pci); head = shm_du_buff_head_alloc(sdb, pci_info.head_size); if (head == NULL) return -EPERM; ser_pci_head(head, pci); if (pci_info.dtc.has_chk) { tail = shm_du_buff_tail_alloc(sdb, pci_info.tail_size); if (tail == NULL) { shm_du_buff_head_release(sdb, pci_info.head_size); return -EPERM; } crc32((uint32_t *) tail, head, tail - head); } return 0; } buffer_t * shm_pci_ser_buf(buffer_t * buf, struct pci * pci) { buffer_t * buffer; assert(buf); assert(pci); buffer = malloc(sizeof(*buffer)); if (buffer == NULL) return NULL; buffer->len = buf->len + pci_info.head_size + pci_info.tail_size; buffer->data = malloc(buffer->len); if (buffer->data == NULL) { free(buffer); return NULL; } ser_pci_head(buffer->data, pci); memcpy(buffer->data + pci_info.head_size, buf->data, buf->len); if (pci_info.dtc.has_chk) crc32((uint32_t *) (buffer->data + pci_info.head_size + buf->len), buffer->data, pci_info.head_size + buf->len); return buffer; } void shm_pci_des(struct shm_du_buff * sdb, struct pci * pci) { uint8_t * head; assert(sdb); assert(pci); head = shm_du_buff_head(sdb); /* FIXME: Add check and operations for Big Endian machines */ memcpy(&pci->pdu_type, head, PDU_TYPE_SIZE); memcpy(&pci->dst_addr, head + pci_info.dst_addr_o, pci_info.dtc.addr_size); memcpy(&pci->src_addr, head + pci_info.src_addr_o, pci_info.dtc.addr_size); memcpy(&pci->dst_cep_id, head + pci_info.dst_cep_id_o, pci_info.dtc.cep_id_size); memcpy(&pci->src_cep_id, head + pci_info.src_cep_id_o, pci_info.dtc.cep_id_size); memcpy(&pci->pdu_length, head + pci_info.pdu_length_o, pci_info.dtc.pdu_length_size); memcpy(&pci->seqno, head + pci_info.seqno_o, pci_info.dtc.seqno_size); memcpy(&pci->qos_id, head + pci_info.qos_id_o, QOS_ID_SIZE); if (pci_info.dtc.has_ttl) { --*(head + pci_info.ttl_o); /* decrease TTL */ memcpy(&pci->ttl, head + pci_info.ttl_o, TTL_SIZE); } else { pci->ttl = 1; } } void shm_pci_shrink(struct shm_du_buff * sdb) { assert(sdb); shm_du_buff_head_release(sdb, pci_info.head_size); shm_du_buff_tail_release(sdb, pci_info.tail_size); }