diff options
author | Dimitri Staessens <dimitri.staessens@ugent.be> | 2018-04-02 23:12:41 +0200 |
---|---|---|
committer | Sander Vrijders <sander.vrijders@ugent.be> | 2018-04-05 10:32:58 +0200 |
commit | e76b3b5d796756ef68687adbed581501cfc4dd27 (patch) | |
tree | ecdb7755ad04b568c129de70a7679eefc8729136 /src | |
parent | 490145fc49bc55280ebf16229d3e78419ec251c6 (diff) | |
download | ouroboros-e76b3b5d796756ef68687adbed581501cfc4dd27.tar.gz ouroboros-e76b3b5d796756ef68687adbed581501cfc4dd27.zip |
ipcpd: Avoid unnecessary copy in eth writer
This writes into the Ethernet device directly from the rdrbuff to
avoid a copy on the write side in the Ethernet IPCPs. This does not
work for the netmap device.
Signed-off-by: Dimitri Staessens <dimitri.staessens@ugent.be>
Signed-off-by: Sander Vrijders <sander.vrijders@ugent.be>
Diffstat (limited to 'src')
-rw-r--r-- | src/ipcpd/eth/eth.c | 70 |
1 files changed, 45 insertions, 25 deletions
diff --git a/src/ipcpd/eth/eth.c b/src/ipcpd/eth/eth.c index 5d42ae76..7a0510c9 100644 --- a/src/ipcpd/eth/eth.c +++ b/src/ipcpd/eth/eth.c @@ -339,6 +339,7 @@ static uint8_t reverse_bits(uint8_t b) } #endif +/* Pass a buffer that contains space for the header. */ static int eth_ipcp_send_frame(const uint8_t * dst_addr, #if defined(BUILD_ETH_DIX) uint16_t deid, @@ -346,17 +347,16 @@ static int eth_ipcp_send_frame(const uint8_t * dst_addr, uint8_t dsap, uint8_t ssap, #endif - const uint8_t * payload, + const uint8_t * frame, size_t len) { uint32_t frame_len = 0; #ifdef BUILD_ETH_LLC uint8_t cf = 0x03; #endif - uint8_t frame[ETH_FRAME_SIZE]; struct eth_frame * e_frame; - assert(payload); + assert(frame); if (len > ETH_MAX_SDU_SIZE) return -1; @@ -383,7 +383,6 @@ static int eth_ipcp_send_frame(const uint8_t * dst_addr, e_frame->cf = cf; frame_len = ETH_HEADER_TOT_SIZE + len; #endif - memcpy(&e_frame->payload, payload, len); #if defined(HAVE_NETMAP) if (poll(ð_data.poll_out, 1, -1) < 0) @@ -430,11 +429,11 @@ static int eth_ipcp_alloc(const uint8_t * dst_addr, len = sizeof(*msg) + ipcp_dir_hash_len(); - buf = malloc(len); + buf = malloc(len + ETH_HEADER_TOT_SIZE); if (buf == NULL) return -1; - msg = (struct mgmt_msg *) buf; + msg = (struct mgmt_msg *) (buf + ETH_HEADER_TOT_SIZE); msg->code = FLOW_REQ; #if defined(BUILD_ETH_DIX) msg->seid = htons(eid); @@ -468,26 +467,40 @@ static int eth_ipcp_alloc_resp(uint8_t * dst_addr, #endif int response) { - struct mgmt_msg msg; + struct mgmt_msg * msg; + uint8_t * buf; + + buf = malloc(sizeof(*msg) + ETH_HEADER_TOT_SIZE); + if (buf == NULL) + return -1; - msg.code = FLOW_REPLY; + msg = (struct mgmt_msg *) (buf + ETH_HEADER_TOT_SIZE); + + msg->code = FLOW_REPLY; #if defined(BUILD_ETH_DIX) - msg.seid = htons(seid); - msg.deid = htons(deid); + msg->seid = htons(seid); + msg->deid = htons(deid); #elif defined(BUILD_ETH_LLC) - msg.ssap = ssap; - msg.dsap = dsap; + msg->ssap = ssap; + msg->dsap = dsap; #endif - msg.response = response; + msg->response = response; - return eth_ipcp_send_frame(dst_addr, + if (eth_ipcp_send_frame(dst_addr, #if defined(BUILD_ETH_DIX) - MGMT_EID, + MGMT_EID, #elif defined(BUILD_ETH_LLC) - reverse_bits(MGMT_SAP), - reverse_bits(MGMT_SAP), + reverse_bits(MGMT_SAP), + reverse_bits(MGMT_SAP), #endif - (uint8_t *) &msg, sizeof(msg)); + buf, sizeof(*msg))) { + free(buf); + return -1; + } + + free(buf); + + return 0; } static int eth_ipcp_req(uint8_t * r_addr, @@ -615,11 +628,11 @@ static int eth_ipcp_name_query_req(const uint8_t * hash, if (shim_data_reg_has(eth_data.shim_data, hash)) { len = sizeof(*msg) + ipcp_dir_hash_len(); - buf = malloc(len); + buf = malloc(len + ETH_HEADER_TOT_SIZE); if (buf == NULL) return -1; - msg = (struct mgmt_msg *) buf; + msg = (struct mgmt_msg *) (buf + ETH_HEADER_TOT_SIZE); msg->code = NAME_QUERY_REPLY; memcpy(msg + 1, hash, ipcp_dir_hash_len()); @@ -924,6 +937,7 @@ static void * eth_ipcp_sdu_writer(void * o) { int fd; struct shm_du_buff * sdb; + size_t len; #if defined(BUILD_ETH_DIX) uint16_t deid; #elif defined(BUILD_ETH_LLC) @@ -946,6 +960,13 @@ static void * eth_ipcp_sdu_writer(void * o) continue; } + len = shm_du_buff_tail(sdb) - shm_du_buff_head(sdb); + + if (shm_du_buff_head_alloc(sdb, ETH_HEADER_TOT_SIZE) + == NULL) { + log_err("Failed to allocate header."); + ipcp_sdb_release(sdb); + } #if defined(BUILD_ETH_DIX) deid = eth_data.fd_to_ef[fd].r_eid; #elif defined(BUILD_ETH_LLC) @@ -963,8 +984,7 @@ static void * eth_ipcp_sdu_writer(void * o) dsap, ssap, #endif shm_du_buff_head(sdb), - shm_du_buff_tail(sdb) - - shm_du_buff_head(sdb)); + len); ipcp_sdb_release(sdb); } pthread_rwlock_unlock(ð_data.flows_lock); @@ -1395,14 +1415,14 @@ static int eth_ipcp_query(const uint8_t * hash) len = sizeof(*msg) + ipcp_dir_hash_len(); - buf = malloc(len); + buf = malloc(len + ETH_HEADER_TOT_SIZE); if (buf == NULL) return -1; - msg = (struct mgmt_msg *) buf; + msg = (struct mgmt_msg *) (buf + ETH_HEADER_TOT_SIZE); msg->code = NAME_QUERY_REQ; - memcpy(buf + sizeof(*msg), hash, ipcp_dir_hash_len()); + memcpy(msg + 1, hash, ipcp_dir_hash_len()); memset(r_addr, 0xff, MAC_SIZE); |