af-packet: make tpacket-v2 block size configurable

With the change of the default tpacket-v2 block size from 32k to 128k,
allow it to be configurable for users who may want to make it larger,
or revert it back to the pre 7.0.9 default of 32k.

Ticket: #7458
pull/12779/head
Jason Ish 1 year ago committed by Victor Julien
parent c342b054f4
commit 5871c6458c

@ -216,6 +216,7 @@ static void *ParseAFPConfig(const char *iface)
aconf->copy_mode = AFP_COPY_MODE_NONE;
aconf->block_timeout = 10;
aconf->block_size = getpagesize() << AFP_BLOCK_SIZE_DEFAULT_ORDER;
aconf->v2_block_size = 0;
#ifdef HAVE_PACKET_EBPF
aconf->ebpf_t_config.cpus_count = UtilCpuGetNumProcessorsConfigured();
#endif
@ -629,6 +630,15 @@ static void *ParseAFPConfig(const char *iface)
aconf->block_timeout = 10;
}
if ((ConfGetChildValueIntWithDefault(if_root, if_default, "v2-block-size", &value)) == 1) {
if (value % getpagesize()) {
SCLogWarning("%s: v2-block-size %" PRIuMAX " must be a multiple of pagesize (%u).",
iface, value, getpagesize());
} else {
aconf->v2_block_size = value;
}
}
(void)ConfGetChildValueBoolWithDefault(if_root, if_default, "disable-promisc", &boolval);
if (boolval) {
SCLogConfig("%s: disabling promiscuous mode", aconf->iface);

@ -317,6 +317,7 @@ typedef struct AFPThreadVars_
int socket;
int ring_size;
int v2_block_size;
int block_size;
int block_timeout;
/* socket buffer size */
@ -1599,6 +1600,63 @@ sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
return 1;
}
static int AFPComputeRingParamsWithBlockSize(AFPThreadVars *ptv, unsigned int block_size)
{
/* Compute structure:
Target is to store all pending packets
with a size equal to MTU + auxdata
And we keep a decent number of block
To do so:
Compute frame_size (aligned to be able to fit in block
Check which block size we need. Blocksize is a 2^n * pagesize
We then need to get order, big enough to have
frame_size < block size
Find number of frame per block (divide)
Fill in packet_req
Compute frame size:
described in packet_mmap.txt
dependent on snaplen (need to use a variable ?)
snaplen: MTU ?
tp_hdrlen determine_version in daq_afpacket
in V1: sizeof(struct tpacket_hdr);
in V2: val in getsockopt(instance->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len)
frame size: TPACKET_ALIGN(snaplen + TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) + sizeof(struct
sockaddr_ll) + ETH_HLEN) - ETH_HLEN);
*/
int tp_hdrlen = sizeof(struct tpacket_hdr);
int snaplen = default_packet_size;
if (snaplen == 0) {
snaplen = GetIfaceMaxPacketSize(ptv->livedev);
if (snaplen <= 0) {
SCLogWarning("%s: unable to get MTU, setting snaplen default of 1514", ptv->iface);
snaplen = 1514;
}
}
ptv->req.v2.tp_frame_size = TPACKET_ALIGN(
snaplen +
TPACKET_ALIGN(TPACKET_ALIGN(tp_hdrlen) + sizeof(struct sockaddr_ll) + ETH_HLEN) -
ETH_HLEN);
ptv->req.v2.tp_block_size = block_size;
int frames_per_block = ptv->req.v2.tp_block_size / ptv->req.v2.tp_frame_size;
if (frames_per_block == 0) {
SCLogError("%s: Frame size bigger than block size", ptv->iface);
return -1;
}
ptv->req.v2.tp_frame_nr = ptv->ring_size;
ptv->req.v2.tp_block_nr = ptv->req.v2.tp_frame_nr / frames_per_block + 1;
/* exact division */
ptv->req.v2.tp_frame_nr = ptv->req.v2.tp_block_nr * frames_per_block;
SCLogPerf("%s: rx ring: block_size=%d block_nr=%d frame_size=%d frame_nr=%d", ptv->iface,
ptv->req.v2.tp_block_size, ptv->req.v2.tp_block_nr, ptv->req.v2.tp_frame_size,
ptv->req.v2.tp_frame_nr);
return 1;
}
#ifdef HAVE_TPACKET_V3
static int AFPComputeRingParamsV3(AFPThreadVars *ptv)
{
@ -1709,29 +1767,51 @@ static int AFPSetupRing(AFPThreadVars *ptv, char *devname)
}
} else {
#endif
for (order = AFP_BLOCK_SIZE_DEFAULT_ORDER; order >= 0; order--) {
if (AFPComputeRingParams(ptv, order) != 1) {
if (ptv->v2_block_size) {
if (AFPComputeRingParamsWithBlockSize(ptv, ptv->v2_block_size) != 1) {
SCLogError("%s: ring parameters are incorrect. Please file a bug report", devname);
return AFP_FATAL_ERROR;
}
r = setsockopt(ptv->socket, SOL_PACKET, PACKET_RX_RING,
(void *) &ptv->req, sizeof(ptv->req));
r = setsockopt(
ptv->socket, SOL_PACKET, PACKET_RX_RING, (void *)&ptv->req, sizeof(ptv->req));
if (r < 0) {
if (errno == ENOMEM) {
SCLogWarning("%s: memory issue with ring parameters. Retrying", devname);
continue;
SCLogError("%s: memory issue with ring parameters", devname);
return AFP_FATAL_ERROR;
}
SCLogError("%s: failed to setup RX Ring: %s", devname, strerror(errno));
return AFP_FATAL_ERROR;
} else {
break;
}
}
if (order < 0) {
SCLogError("%s: failed to setup RX Ring (order 0 failed)", devname);
return AFP_FATAL_ERROR;
} else {
for (order = AFP_BLOCK_SIZE_DEFAULT_ORDER; order >= 0; order--) {
if (AFPComputeRingParams(ptv, order) != 1) {
SCLogError(
"%s: ring parameters are incorrect. Please file a bug report", devname);
return AFP_FATAL_ERROR;
}
r = setsockopt(ptv->socket, SOL_PACKET, PACKET_RX_RING, (void *)&ptv->req,
sizeof(ptv->req));
if (r < 0) {
if (errno == ENOMEM) {
SCLogWarning("%s: memory issue with ring parameters. Retrying", devname);
continue;
}
SCLogError("%s: failed to setup RX Ring: %s", devname, strerror(errno));
return AFP_FATAL_ERROR;
} else {
break;
}
}
if (order < 0) {
SCLogError("%s: failed to setup RX Ring (order 0 failed)", devname);
return AFP_FATAL_ERROR;
}
}
#ifdef HAVE_TPACKET_V3
}
@ -2516,6 +2596,7 @@ TmEcode ReceiveAFPThreadInit(ThreadVars *tv, const void *initdata, void **data)
ptv->buffer_size = afpconfig->buffer_size;
ptv->ring_size = afpconfig->ring_size;
ptv->v2_block_size = afpconfig->v2_block_size;
ptv->block_size = afpconfig->block_size;
ptv->block_timeout = afpconfig->block_timeout;

@ -90,6 +90,8 @@ typedef struct AFPIfaceConfig_
int block_size;
/* block timeout for tpacket_v3 in milliseconds */
int block_timeout;
/* block size for tpacket v2 */
int v2_block_size;
/* cluster param */
uint16_t cluster_id;
int cluster_type;

@ -684,6 +684,10 @@ af-packet:
# tpacket_v3 block timeout: an open block is passed to userspace if it is not
# filled after block-timeout milliseconds.
#block-timeout: 10
# Block size for tpacket-v2. In 7.0.9 the built-in default was
# increased from 32768 to 131072. Uncomment and reset back to
# 32768 if this is a problem with your configuration.
#v2-block-size: 131072
# On busy systems, set it to yes to help recover from a packet drop
# phase. This will result in some packets (at max a ring flush) not being inspected.
#use-emergency-flush: yes

Loading…
Cancel
Save