diff options
Diffstat (limited to 'src/ipcpd/shim-eth-llc')
-rw-r--r-- | src/ipcpd/shim-eth-llc/main.c | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/src/ipcpd/shim-eth-llc/main.c b/src/ipcpd/shim-eth-llc/main.c index ca6008cf..cd913de4 100644 --- a/src/ipcpd/shim-eth-llc/main.c +++ b/src/ipcpd/shim-eth-llc/main.c @@ -106,6 +106,7 @@ struct { uint8_t * rx_ring; uint8_t * tx_ring; int tx_offset; + pthread_mutex_t tx_lock; #endif flow_set_t * np1_flows; fqueue_t * fq; @@ -166,6 +167,10 @@ static int eth_llc_data_init(void) pthread_rwlock_init(ð_llc_data.flows_lock, NULL); +#if defined(PACKET_RX_RING) && defined(PACKET_TX_RING) + pthread_mutex_init(ð_llc_data.tx_lock, NULL); +#endif + return 0; } @@ -177,6 +182,9 @@ void eth_llc_data_fini(void) free(eth_llc_data.fd_to_ef); free(eth_llc_data.ef_to_fd); pthread_rwlock_destroy(ð_llc_data.flows_lock); +#if defined(PACKET_RX_RING) && defined(PACKET_TX_RING) + pthread_mutex_destroy(ð_llc_data.tx_lock); +#endif } static uint8_t reverse_bits(uint8_t b) @@ -215,6 +223,8 @@ static int eth_llc_ipcp_send_frame(uint8_t * dst_addr, return -1; #if defined(PACKET_RX_RING) && defined(PACKET_TX_RING) + pthread_mutex_lock(ð_llc_data.tx_lock); + header = (void *) (eth_llc_data.tx_ring + eth_llc_data.tx_offset * SHM_RDRB_BLOCK_SIZE); @@ -223,11 +233,16 @@ static int eth_llc_ipcp_send_frame(uint8_t * dst_addr, pfd.revents = 0; pfd.events = POLLIN | POLLRDNORM | POLLERR; + pthread_mutex_unlock(ð_llc_data.tx_lock); + if (poll(&pfd, 1, -1) <= 0) { log_err("Failed to poll."); + pthread_mutex_lock(ð_llc_data.tx_lock); continue; } + pthread_mutex_lock(ð_llc_data.tx_lock); + header = (void *) (eth_llc_data.tx_ring + eth_llc_data.tx_offset * SHM_RDRB_BLOCK_SIZE); @@ -235,6 +250,8 @@ static int eth_llc_ipcp_send_frame(uint8_t * dst_addr, frame = (uint8_t *) header + TPACKET_HDRLEN - sizeof(struct sockaddr_ll); + + pthread_mutex_unlock(ð_llc_data.tx_lock); #endif llc_frame = (struct eth_llc_frame *) frame; @@ -257,16 +274,21 @@ static int eth_llc_ipcp_send_frame(uint8_t * dst_addr, frame_len = ETH_HEADER_SIZE + LLC_HEADER_SIZE + len; #if defined(PACKET_RX_RING) && defined(PACKET_TX_RING) + pthread_mutex_lock(ð_llc_data.tx_lock); + header->tp_len = frame_len; header->tp_status = TP_STATUS_SEND_REQUEST; if (send(eth_llc_data.s_fd, NULL, 0, MSG_DONTWAIT) < 0) { + pthread_mutex_unlock(ð_llc_data.tx_lock); log_err("Failed to write frame into TX_RING."); return -1; } eth_llc_data.tx_offset = (eth_llc_data.tx_offset + 1) & ((SHM_BUFFER_SIZE) - 1); + + pthread_mutex_unlock(ð_llc_data.tx_lock); #else if (sendto(eth_llc_data.s_fd, frame, @@ -386,7 +408,7 @@ static int eth_llc_ipcp_sap_alloc_reply(uint8_t ssap, int fd = -1; pthread_rwlock_rdlock(&ipcpi.state_lock); - pthread_rwlock_rdlock(& eth_llc_data.flows_lock); + pthread_rwlock_wrlock(& eth_llc_data.flows_lock); fd = eth_llc_data.ef_to_fd[dsap]; if (fd < 0) { @@ -519,23 +541,33 @@ static void * eth_llc_ipcp_sdu_reader(void * o) while (true) { #if defined(PACKET_RX_RING) && defined(PACKET_TX_RING) + pthread_mutex_lock(ð_llc_data.tx_lock); + header = (void *) (eth_llc_data.rx_ring + offset * SHM_RDRB_BLOCK_SIZE); + while (!(header->tp_status & TP_STATUS_USER)) { pfd.fd = eth_llc_data.s_fd; pfd.revents = 0; pfd.events = POLLIN | POLLRDNORM | POLLERR; + pthread_mutex_unlock(ð_llc_data.tx_lock); + if (poll(&pfd, 1, -1) <= 0) { log_err("Failed to poll."); + pthread_mutex_lock(ð_llc_data.tx_lock); continue; } + pthread_mutex_lock(ð_llc_data.tx_lock); + header = (void *) (eth_llc_data.rx_ring + offset * SHM_RDRB_BLOCK_SIZE); } buf = (uint8_t * ) header + header->tp_mac; + + pthread_mutex_unlock(ð_llc_data.tx_lock); #else frame_len = recv(eth_llc_data.s_fd, buf, SHIM_ETH_LLC_MAX_SDU_SIZE, 0); @@ -566,8 +598,12 @@ static void * eth_llc_ipcp_sdu_reader(void * o) if (length > 0x05FF) { /* DIX */ #if defined(PACKET_RX_RING) && defined(PACKET_TX_RING) + pthread_mutex_lock(ð_llc_data.tx_lock); + offset = (offset + 1) & ((SHM_BUFFER_SIZE) -1); header->tp_status = TP_STATUS_KERNEL; + + pthread_mutex_unlock(ð_llc_data.tx_lock); #endif continue; } @@ -588,8 +624,12 @@ static void * eth_llc_ipcp_sdu_reader(void * o) if (fd < 0) { pthread_rwlock_unlock(ð_llc_data.flows_lock); #if defined(PACKET_RX_RING) && defined(PACKET_TX_RING) + pthread_mutex_lock(ð_llc_data.tx_lock); + offset = (offset + 1) & ((SHM_BUFFER_SIZE) - 1); header->tp_status = TP_STATUS_KERNEL; + + pthread_mutex_unlock(ð_llc_data.tx_lock); #endif continue; } @@ -599,8 +639,12 @@ static void * eth_llc_ipcp_sdu_reader(void * o) llc_frame->src_hwaddr, MAC_SIZE)) { pthread_rwlock_unlock(ð_llc_data.flows_lock); #if defined(PACKET_RX_RING) && defined(PACKET_TX_RING) + pthread_mutex_lock(ð_llc_data.tx_lock); + offset = (offset + 1) & ((SHM_BUFFER_SIZE) -1); header->tp_status = TP_STATUS_KERNEL; + + pthread_mutex_unlock(ð_llc_data.tx_lock); #endif continue; } @@ -610,8 +654,12 @@ static void * eth_llc_ipcp_sdu_reader(void * o) flow_write(fd, &llc_frame->payload, length); } #if defined(PACKET_RX_RING) && defined(PACKET_TX_RING) + pthread_mutex_lock(ð_llc_data.tx_lock); + offset = (offset + 1) & ((SHM_BUFFER_SIZE) - 1); header->tp_status = TP_STATUS_KERNEL; + + pthread_mutex_unlock(ð_llc_data.tx_lock); #endif } |