IO fixes/enhancements

This commit is contained in:
Christian Giese
2022-11-02 17:52:51 +01:00
committed by Christian Giese
parent 4d8de4fd34
commit 425f384efd
4 changed files with 42 additions and 63 deletions
+2 -4
View File
@@ -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;
+28 -46
View File
@@ -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++;
+2
View File
@@ -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;
+10 -13
View File
@@ -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) {