Skip to content
LinkState
Go back

Tcpdump Cut the Ceiling in Half

Introduction to Benchmarking and Packet Capture

Benchmarking is a crucial step in evaluating the performance of network systems. It involves measuring the throughput, latency, and other key performance indicators (KPIs) of a system under various loads. There are several benchmarking methodologies, including synthetic benchmarks, which use artificial workloads to stress the system, and real-world benchmarks, which use actual application workloads. In this article, we will focus on the impact of packet capture on benchmarking results.

The Mysterious Regression

We started by running a benchmark on a network system using a synthetic workload. The initial results showed a throughput of 10 Gbps and a latency of 10 μs. However, when we enabled packet capture using AF_PACKET, we observed a mysterious regression in the benchmark results. The throughput dropped to 8 Gbps, and the latency increased to 20 μs.

Understanding AF_PACKET Capture

AF_PACKET is a Linux socket type that allows users to capture and transmit raw network packets. It provides a low-level interface for packet capture and is commonly used in network analysis and benchmarking tools. AF_PACKET capture can introduce additional overhead and latency into the network datapath. This is because the packet capture process involves copying packets from the network interface into user-space, which can consume CPU cycles and memory bandwidth.

AF_PACKET Capture Point and Its Effects

The capture point is the location in the network datapath where packets are captured. Choosing the optimal capture point is crucial to minimize distortion in the datapath. In Linux, the capture point can be set using the SO_ATTACH_FILTER socket option.

#include <linux/socket.h>
#include <linux/filter.h>
int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd < 0) {
    perror("socket");
    return -1;
}
struct sock_filter filter_code[] = {
    { 0x28, 0, 0, 0x0000000c }, // Load packet length
    { 0x15, 0, 1, 0x00000800 }, // Jump if packet length > 2048
    { 0x06, 0, 0, 0x00000000 }, // Return
    { 0x06, 0, 0, 0x00000000 }, // Return
};
struct sock_fprog filter_prog = {
    .len = sizeof(filter_code) / sizeof(struct sock_filter),
    .filter = filter_code,
};
if (setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, sizeof(filter_prog)) < 0) {
    perror("setsockopt");
    return -1;
}

Ring Settings and Their Role in Packet Capture

Ring settings refer to the configuration of the packet capture buffer, including its size and number of packets. The ring settings can significantly impact the performance of packet capture. To optimize performance, the ring settings should be configured to minimize packet loss and reduce CPU overhead.

sudo ethtool -C eth0 rx-frames 4096
sudo ethtool -C eth0 rx-usecs 10

Copy Cost and Its Impact on Datapath

Copy cost refers to the overhead of copying packets from the network interface into user-space. This cost can be significant, especially for high-throughput networks. The copy cost can be measured using tools such as perf or sysdig.

#include <linux/socket.h>
#include <linux/filter.h>
int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd < 0) {
    perror("socket");
    return -1;
}
// Use a zero-copy packet capture mechanism, such as AF_PACKET's TPACKET_V3
struct packet_mreq mr;
memset(&mr, 0, sizeof(mr));
mr.mr_type = PACKET_RX_RING;
mr.mr_count = 4096;
if (setsockopt(sockfd, SOL_PACKET, PACKET_RX_RING, &mr, sizeof(mr)) < 0) {
    perror("setsockopt");
    return -1;
}

Common issues in packet capture include packet loss, CPU overhead, and memory allocation failures. Debugging tools such as tcpdump, Wireshark, and sysdig can be used to troubleshoot packet capture-related issues.

sudo tcpdump -i eth0 -w capture.pcap
sudo sysdig -c "packet capture"

Scaling Limitations of Packet Capture

Packet capture can be challenging to scale in large networks, especially when dealing with high-throughput traffic. AF_PACKET has limitations in high-throughput environments, including packet loss and CPU overhead.

#include <linux/socket.h>
#include <linux/filter.h>
int sockfd1 = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
int sockfd2 = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
// Use multiple sockets to capture packets from multiple interfaces
struct packet_mreq mr;
memset(&mr, 0, sizeof(mr));
mr.mr_type = PACKET_RX_RING;
mr.mr_count = 4096;
if (setsockopt(sockfd1, SOL_PACKET, PACKET_RX_RING, &mr, sizeof(mr)) < 0) {
    perror("setsockopt");
    return -1;
}
if (setsockopt(sockfd2, SOL_PACKET, PACKET_RX_RING, &mr, sizeof(mr)) < 0) {
    perror("setsockopt");
    return -1;
}

Best Practices for Accurate Benchmarking with Packet Capture

To minimize distortion in the datapath, packet capture should be configured to introduce minimal overhead and latency. Packet capture settings, such as ring size and packet buffering, should be optimized for benchmarking to ensure accurate results.

sudo ethtool -C eth0 rx-frames 4096
sudo ethtool -C eth0 rx-usecs 10

Advanced Topics in Packet Capture and Benchmarking

Additional tools, such as iperf and netperf, can be used to analyze network performance and benchmarking results. Packet capture can be integrated with other benchmarking tools, such as sysdig and perf, to provide a comprehensive understanding of network performance.

#include <linux/socket.h>
#include <linux/filter.h>
int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd < 0) {
    perror("socket");
    return -1;
}
// Use sysdig to capture system calls and packet capture
sudo sysdig -c "packet capture" -c "syscalls"

Conclusion and Future Directions

In this article, we explored the impact of packet capture on benchmarking results, with a focus on AF_PACKET capture. We discussed the effects of capture point, ring settings, and copy cost on the datapath and provided examples of how to optimize packet capture settings for benchmarking. Future research directions include exploring new packet capture mechanisms, such as zero-copy packet capture, and integrating packet capture with other benchmarking tools.

#include <linux/socket.h>
#include <linux/filter.h>
int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd < 0) {
    perror("socket");
    return -1;
}
// Use emerging trends, such as eBPF, to optimize packet capture and benchmarking
sudo bpftool prog load eBPF_program.o /sys/fs/bpf/eBPF_program

Share this post on:

Previous Post
Aggregate withdrawal races that create transient loops
Next Post
Why cloned images lose tcpdump and raw sockets