From 425f384efd0ff8c2e92a856d4fe1b5bb475f0217 Mon Sep 17 00:00:00 2001 From: Christian Giese Date: Mon, 26 Sep 2022 07:44:45 +0000 Subject: [PATCH] IO fixes/enhancements --- code/bngblaster/src/io/io_def.h | 6 +- code/bngblaster/src/io/io_packet_mmap.c | 74 ++++++++++--------------- code/bngblaster/src/io/io_raw.c | 2 + code/bngblaster/src/io/io_socket.c | 23 ++++---- 4 files changed, 42 insertions(+), 63 deletions(-) diff --git a/code/bngblaster/src/io/io_def.h b/code/bngblaster/src/io/io_def.h index cdb2ec7f..3e1fbcb9 100644 --- a/code/bngblaster/src/io/io_def.h +++ b/code/bngblaster/src/io/io_def.h @@ -50,10 +50,8 @@ typedef struct io_handle_ { struct sockaddr_ll addr; uint8_t *ring; /* ring buffer */ - uint16_t cursor; /* ring buffer cursor */ - uint16_t queued; - bool polled; - bool ctrl; + unsigned int cursor; /* ring buffer cursor */ + unsigned int queued; io_thread_s *thread; bbl_interface_s *interface; diff --git a/code/bngblaster/src/io/io_packet_mmap.c b/code/bngblaster/src/io/io_packet_mmap.c index 83f8efa8..4f51e941 100644 --- a/code/bngblaster/src/io/io_packet_mmap.c +++ b/code/bngblaster/src/io/io_packet_mmap.c @@ -20,16 +20,14 @@ static void poll_kernel(io_handle_s *io, short events) { - struct pollfd fds[1] = {0}; - fds[0].fd = io->fd; - fds[0].events = events; - fds[0].revents = 0; + struct pollfd pollset; + pollset.fd = io->fd; + pollset.events = events; + pollset.revents = 0; io->stats.polled++; - if(poll(fds, 1, 0) == -1) { + if(poll(&pollset, 1, 0) == -1) { LOG(IO, "Failed to poll interface %s", io->interface->name); - } else { - io->polled = true; } } @@ -132,20 +130,14 @@ io_packet_mmap_tx_job(timer_s *timer) assert(io->thread == NULL); frame_ptr = io->ring + (io->cursor * io->req.tp_frame_size); - tphdr = (struct tpacket2_hdr *)frame_ptr; - if(tphdr->tp_status != TP_STATUS_AVAILABLE) { - if(io->polled) { - /* We already polled kernel. */ - return; - } - /* If no buffer is available poll kernel. */ - poll_kernel(io, POLLOUT); + tphdr = (struct tpacket2_hdr*)frame_ptr; + if(!(tphdr->tp_status != TP_STATUS_AVAILABLE)) { + /* If no buffer is available poll kernel */ + poll_kernel(io, POLLIN); + io->stats.no_buffer++; } else { - io->polled = false; - /* Get TX timestamp */ clock_gettime(CLOCK_MONOTONIC, &io->timestamp); - while(tx_result != EMPTY) { /* Check if this slot available for writing. */ if(tphdr->tp_status != TP_STATUS_AVAILABLE) { @@ -155,19 +147,18 @@ io_packet_mmap_tx_job(timer_s *timer) io->buf = frame_ptr + TPACKET2_HDRLEN - sizeof(struct sockaddr_ll); tx_result = bbl_tx(interface, io->buf, &io->buf_len); if(tx_result == PROTOCOL_SUCCESS) { - io->queued++; - tphdr->tp_len = io->buf_len; - tphdr->tp_status = TP_STATUS_SEND_REQUEST; - io->stats.packets++; - io->stats.bytes += io->buf_len; /* Dump the packet into pcap file. */ if(g_ctx->pcap.write_buf) { pcap = true; pcapng_push_packet_header(&io->timestamp, io->buf, io->buf_len, interface->pcap_index, PCAPNG_EPB_FLAGS_OUTBOUND); } - /* Request send from kernel. */ + tphdr->tp_len = io->buf_len; tphdr->tp_status = TP_STATUS_SEND_REQUEST; + io->queued++; + io->stats.packets++; + io->stats.bytes += io->buf_len; + /* Get next slot. */ io->cursor = (io->cursor + 1) % io->req.tp_frame_nr; frame_ptr = io->ring + (io->cursor * io->req.tp_frame_size); @@ -181,7 +172,7 @@ io_packet_mmap_tx_job(timer_s *timer) if(io->queued) { /* Notify kernel. */ - if(sendto(io->fd, NULL, 0, 0, NULL, 0) == -1) { + if(sendto(io->fd, NULL, 0, 0, NULL, 0) < 0) { LOG(IO, "PACKET_MMAP sendto on interface %s failed with error %s (%d)\n", interface->name, strerror(errno), errno); io->stats.io_errors++; @@ -266,15 +257,10 @@ io_packet_mmap_thread_tx_job(timer_s *timer) frame_ptr = io->ring + (io->cursor * io->req.tp_frame_size); tphdr = (struct tpacket2_hdr *)frame_ptr; if(tphdr->tp_status != TP_STATUS_AVAILABLE) { - if(io->polled) { - /* We already polled kernel. */ - return; - } /* If no buffer is available poll kernel. */ poll_kernel(io, POLLOUT); + io->stats.no_buffer++; } else { - io->polled = false; - while((slot = bbl_txq_read_slot(txq))) { /* Check if this slot available for writing. */ if(tphdr->tp_status != TP_STATUS_AVAILABLE) { @@ -283,14 +269,12 @@ io_packet_mmap_thread_tx_job(timer_s *timer) } io->buf = frame_ptr + TPACKET2_HDRLEN - sizeof(struct sockaddr_ll); io->buf_len = slot->packet_len; - io->queued++; - io->stats.packets++; - io->stats.bytes += slot->packet_len; memcpy(io->buf, slot->packet, slot->packet_len); tphdr->tp_len = io->buf_len; tphdr->tp_status = TP_STATUS_SEND_REQUEST; - /* Request send from kernel. */ - tphdr->tp_status = TP_STATUS_SEND_REQUEST; + io->queued++; + io->stats.packets++; + io->stats.bytes += io->buf_len; /* Get next slot. */ io->cursor = (io->cursor + 1) % io->req.tp_frame_nr; frame_ptr = io->ring + (io->cursor * io->req.tp_frame_size); @@ -301,7 +285,7 @@ io_packet_mmap_thread_tx_job(timer_s *timer) if(io->queued) { /* Notify kernel. */ - if(sendto(io->fd, NULL, 0, 0, NULL, 0) == -1) { + if(sendto(io->fd, NULL, 0, 0, NULL, 0) < 0) { LOG(IO, "PACKET_MMAP sendto on interface %s failed with error %s (%d)\n", interface->name, strerror(errno), errno); io->stats.io_errors++; @@ -327,28 +311,26 @@ io_packet_mmap_send(io_handle_s *io, uint8_t *buf, uint16_t len) frame_ptr = io->ring + (io->cursor * io->req.tp_frame_size); tphdr = (struct tpacket2_hdr *)frame_ptr; if(tphdr->tp_status != TP_STATUS_AVAILABLE) { - if(!io->polled) { - /* If no buffer is available poll kernel. */ - poll_kernel(io, POLLOUT); - } + /* If no buffer is available poll kernel. */ + poll_kernel(io, POLLOUT); io->stats.no_buffer++; return false; } - io->polled = false; - io->queued++; + tphdr_buf = frame_ptr + TPACKET2_HDRLEN - sizeof(struct sockaddr_ll); memcpy(tphdr_buf, buf, len); tphdr->tp_len = len; tphdr->tp_status = TP_STATUS_SEND_REQUEST; - /* Request send from kernel. */ - tphdr->tp_status = TP_STATUS_SEND_REQUEST; + io->queued++; + io->stats.packets++; + io->stats.bytes += len; /* Get next slot. */ io->cursor = (io->cursor + 1) % io->req.tp_frame_nr; frame_ptr = io->ring + (io->cursor * io->req.tp_frame_size); tphdr = (struct tpacket2_hdr *)frame_ptr; if(tphdr->tp_status != TP_STATUS_AVAILABLE) { /* Notify kernel. */ - if(sendto(io->fd, NULL, 0, 0, NULL, 0) == -1) { + if(sendto(io->fd, NULL, 0, 0, NULL, 0) < 0) { LOG(IO, "PACKET_MMAP sendto on interface %s failed with error %s (%d)\n", interface->name, strerror(errno), errno); io->stats.io_errors++; diff --git a/code/bngblaster/src/io/io_raw.c b/code/bngblaster/src/io/io_raw.c index bffe2af8..1844c425 100644 --- a/code/bngblaster/src/io/io_raw.c +++ b/code/bngblaster/src/io/io_raw.c @@ -118,6 +118,8 @@ io_raw_thread_rx_run_fn(io_thread_s *thread) struct timespec sleep, rem; + assert(io->direction == IO_INGRESS); + sleep.tv_sec = 0; sleep.tv_nsec = 0; diff --git a/code/bngblaster/src/io/io_socket.c b/code/bngblaster/src/io/io_socket.c index 658c2e85..f2bc5447 100644 --- a/code/bngblaster/src/io/io_socket.c +++ b/code/bngblaster/src/io/io_socket.c @@ -35,7 +35,7 @@ set_qdisc_bypass(io_handle_s *io) { /* Set fanout group. */ static bool set_fanout(io_handle_s *io) { - if(io->direction == IO_INGRESS && io->fanout_id) { + if(io->fanout_id) { int fanout_arg = (io->fanout_id | (io->fanout_type << 16)); if (setsockopt(io->fd, SOL_PACKET, PACKET_FANOUT, &fanout_arg, sizeof(fanout_arg)) == -1) { LOG(ERROR, "Failed to set fanout group for interface %s - %s (%d)\n", @@ -67,22 +67,21 @@ set_ring(io_handle_s *io, int slots) { * - tp_frame_nr must be exactly frames_per_block*tp_block_nr * Note that tp_block_size should be chosen to be a power of two * or there will be a waste of memory. */ - size_t ring_size = 0; + unsigned int ring_size = 0; int flag = 0; - if(io->direction == IO_INGRESS) { flag = PACKET_RX_RING; } else { flag = PACKET_TX_RING; } - io->req.tp_block_size = sysconf(_SC_PAGESIZE); /* 4096 */ - io->req.tp_frame_size =io->req.tp_block_size/2; /* 2048 */ - io->req.tp_block_nr = slots/2; + io->req.tp_block_size = getpagesize(); /* 4096 */ + io->req.tp_frame_size = io->req.tp_block_size; + io->req.tp_block_nr = slots; io->req.tp_frame_nr = slots; ring_size = io->req.tp_block_nr * io->req.tp_block_size; - LOG(DEBUG, "Setup %lu byte packet_mmap ringbuffer (%d slots) for interface %s\n", + LOG(DEBUG, "Setup %u byte packet_mmap ringbuffer (%d slots) for interface %s\n", ring_size, slots, io->interface->name); if (setsockopt(io->fd, SOL_PACKET, flag, &io->req, sizeof(struct tpacket_req)) == -1) { LOG(ERROR, "Allocating ringbuffer error for interface %s - %s (%d)\n", @@ -105,25 +104,23 @@ io_socket_open(io_handle_s *io) { assert(io->mode == IO_MODE_PACKET_MMAP || io->mode == IO_MODE_RAW); int protocol = 0; + int slots = config->io_slots_tx; + if(io->direction == IO_INGRESS) { protocol = htobe16(ETH_P_ALL); - } - - uint16_t slots = config->io_slots_tx; - if(io->direction == IO_INGRESS) { slots = config->io_slots_rx; } /* Open RAW socket for all ethertypes. * https://man7.org/linux/man-pages/man7/packet.7.html */ - io->fd = socket(PF_PACKET, SOCK_RAW | SOCK_NONBLOCK, protocol); + io->fd = socket(AF_PACKET, SOCK_RAW|SOCK_NONBLOCK, protocol); if(io->fd == -1) { LOG(ERROR, "Failed to open socket for interface %s - %s (%d)\n", io->interface->name, strerror(errno), errno); return false; } /* Limit socket to the given interface index. */ - io->addr.sll_family = PF_PACKET; + io->addr.sll_family = AF_PACKET; io->addr.sll_ifindex = io->interface->ifindex; io->addr.sll_protocol = protocol; if (bind(io->fd, (struct sockaddr*)&io->addr, sizeof(io->addr)) == -1) {