af-packet: put ring setup in a separate function

pull/2091/head
Eric Leblond 10 years ago committed by Victor Julien
parent 7fa963718f
commit c7bde9dff6

@ -1592,17 +1592,153 @@ static int AFPComputeRingParamsV3(AFPThreadVars *ptv)
return 1;
}
static int AFPSetupRing(AFPThreadVars *ptv, char *devname)
{
int val;
unsigned int len = sizeof(val), i;
unsigned int ring_buflen;
uint8_t * ring_buf;
int order;
int r;
if (ptv->flags & AFP_TPACKET_V3) {
val = TPACKET_V3;
} else {
val = TPACKET_V2;
}
if (getsockopt(ptv->socket, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
if (errno == ENOPROTOOPT) {
if (ptv->flags & AFP_TPACKET_V3) {
SCLogError(SC_ERR_AFP_CREATE,
"Too old kernel giving up (need 3.2 for TPACKET_V3)");
} else {
SCLogError(SC_ERR_AFP_CREATE,
"Too old kernel giving up (need 2.6.27 at least)");
}
}
SCLogError(SC_ERR_AFP_CREATE, "Error when retrieving packet header len");
return AFP_FATAL_ERROR;
}
if (ptv->flags & AFP_TPACKET_V3) {
val = TPACKET_V3;
} else {
val = TPACKET_V2;
}
if (setsockopt(ptv->socket, SOL_PACKET, PACKET_VERSION, &val,
sizeof(val)) < 0) {
SCLogError(SC_ERR_AFP_CREATE,
"Can't activate TPACKET_V2/TPACKET_V3 on packet socket: %s",
strerror(errno));
return AFP_FATAL_ERROR;
}
/* Allocate RX ring */
if (ptv->flags & AFP_TPACKET_V3) {
if (AFPComputeRingParamsV3(ptv) != 1) {
return AFP_FATAL_ERROR;
}
r = setsockopt(ptv->socket, SOL_PACKET, PACKET_RX_RING,
(void *) &ptv->req3, sizeof(ptv->req3));
if (r < 0) {
SCLogError(SC_ERR_MEM_ALLOC,
"Unable to allocate RX Ring for iface %s: (%d) %s",
devname,
errno,
strerror(errno));
return AFP_FATAL_ERROR;
}
} else {
#define DEFAULT_ORDER 3
for (order = DEFAULT_ORDER; order >= 0; order--) {
if (AFPComputeRingParams(ptv, order) != 1) {
SCLogInfo("Ring parameter are incorrect. Please correct the devel");
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) {
SCLogInfo("Memory issue with ring parameters. Retrying.");
continue;
}
SCLogError(SC_ERR_MEM_ALLOC,
"Unable to allocate RX Ring for iface %s: (%d) %s",
devname,
errno,
strerror(errno));
return AFP_FATAL_ERROR;
} else {
break;
}
}
if (order < 0) {
SCLogError(SC_ERR_MEM_ALLOC,
"Unable to allocate RX Ring for iface %s (order 0 failed)",
devname);
return AFP_FATAL_ERROR;
}
}
/* Allocate the Ring */
if (ptv->flags & AFP_TPACKET_V3) {
ring_buflen = ptv->req3.tp_block_nr * ptv->req3.tp_block_size;
} else {
ring_buflen = ptv->req.tp_block_nr * ptv->req.tp_block_size;
}
ring_buf = mmap(0, ring_buflen, PROT_READ|PROT_WRITE,
MAP_SHARED, ptv->socket, 0);
if (ring_buf == MAP_FAILED) {
SCLogError(SC_ERR_MEM_ALLOC, "Unable to mmap");
goto mmap_err;
}
if (ptv->flags & AFP_TPACKET_V3) {
ptv->ring_v3 = SCMalloc(ptv->req3.tp_block_nr * sizeof(*ptv->ring_v3));
if (!ptv->ring_v3) {
SCLogError(SC_ERR_MEM_ALLOC, "Unable to malloc ptv ring_v3");
goto mmap_err;
}
for (i = 0; i < ptv->req3.tp_block_nr; ++i) {
ptv->ring_v3[i].iov_base = ring_buf + (i * ptv->req3.tp_block_size);
ptv->ring_v3[i].iov_len = ptv->req3.tp_block_size;
}
} else {
/* allocate a ring for each frame header pointer*/
ptv->ring_v2 = SCMalloc(ptv->req.tp_frame_nr * sizeof (union thdr *));
if (ptv->ring_v2 == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate frame buf");
goto mmap_err;
}
memset(ptv->ring_v2, 0, ptv->req.tp_frame_nr * sizeof (union thdr *));
/* fill the header ring with proper frame ptr*/
ptv->frame_offset = 0;
for (i = 0; i < ptv->req.tp_block_nr; ++i) {
void *base = &ring_buf[i * ptv->req.tp_block_size];
unsigned int j;
for (j = 0; j < ptv->req.tp_block_size / ptv->req.tp_frame_size; ++j, ++ptv->frame_offset) {
(((union thdr **)ptv->ring_v2)[ptv->frame_offset]) = base;
base += ptv->req.tp_frame_size;
}
}
ptv->frame_offset = 0;
}
return 0;
mmap_err:
/* Packet mmap does the cleaning when socket is closed */
return AFP_FATAL_ERROR;
}
static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
{
int r;
int ret = AFP_FATAL_ERROR;
struct packet_mreq sock_params;
struct sockaddr_ll bind_address;
int order;
unsigned int i;
int if_idx;
unsigned int ring_buflen;
uint8_t * ring_buf;
/* open socket */
ptv->socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
@ -1633,7 +1769,7 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
SCLogError(SC_ERR_AFP_CREATE,
"Couldn't switch iface %s to promiscuous, error %s",
devname, strerror(errno));
goto frame_err;
goto socket_err;
}
}
@ -1659,7 +1795,7 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
SCLogError(SC_ERR_AFP_CREATE,
"Couldn't set buffer size to %d on iface %s, error %s",
ptv->buffer_size, devname, strerror(errno));
goto frame_err;
goto socket_err;
}
}
@ -1677,7 +1813,7 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
}
}
ret = AFP_RECOVERABLE_ERROR;
goto frame_err;
goto socket_err;
}
#ifdef HAVE_PACKET_FANOUT
@ -1692,7 +1828,7 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
SCLogError(SC_ERR_AFP_CREATE,
"Coudn't set fanout mode, error %s",
strerror(errno));
goto frame_err;
goto socket_err;
}
}
#endif
@ -1705,7 +1841,7 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
ptv->iface);
}
ret = AFP_RECOVERABLE_ERROR;
goto frame_err;
goto socket_err;
}
if ((if_flags & IFF_UP) == 0) {
if (verbose) {
@ -1714,129 +1850,13 @@ static int AFPCreateSocket(AFPThreadVars *ptv, char *devname, int verbose)
ptv->iface);
}
ret = AFP_RECOVERABLE_ERROR;
goto frame_err;
goto socket_err;
}
if (ptv->flags & AFP_RING_MODE) {
int val;
unsigned int len = sizeof(val);
if (ptv->flags & AFP_TPACKET_V3) {
val = TPACKET_V3;
} else {
val = TPACKET_V2;
}
if (getsockopt(ptv->socket, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
if (errno == ENOPROTOOPT) {
if (ptv->flags & AFP_TPACKET_V3) {
SCLogError(SC_ERR_AFP_CREATE,
"Too old kernel giving up (need 3.2 for TPACKET_V3)");
} else {
SCLogError(SC_ERR_AFP_CREATE,
"Too old kernel giving up (need 2.6.27 at least)");
}
}
SCLogError(SC_ERR_AFP_CREATE, "Error when retrieving packet header len");
goto socket_err;
}
if (ptv->flags & AFP_TPACKET_V3) {
val = TPACKET_V3;
} else {
val = TPACKET_V2;
}
if (setsockopt(ptv->socket, SOL_PACKET, PACKET_VERSION, &val,
sizeof(val)) < 0) {
SCLogError(SC_ERR_AFP_CREATE,
"Can't activate TPACKET_V2/TPACKET_V3 on packet socket: %s",
strerror(errno));
goto socket_err;
}
/* Allocate RX ring */
if (ptv->flags & AFP_TPACKET_V3) {
if (AFPComputeRingParamsV3(ptv) != 1) {
SCLogInfo("Ring parameter are incorrect. Please correct the devel");
goto socket_err;
}
r = setsockopt(ptv->socket, SOL_PACKET, PACKET_RX_RING,
(void *) &ptv->req3, sizeof(ptv->req3));
} else {
#define DEFAULT_ORDER 3
for (order = DEFAULT_ORDER; order >= 0; order--) {
if (AFPComputeRingParams(ptv, order) != 1) {
SCLogInfo("Ring parameter are incorrect. Please correct the devel");
goto socket_err;
}
r = setsockopt(ptv->socket, SOL_PACKET, PACKET_RX_RING,
(void *) &ptv->req, sizeof(ptv->req));
if (r < 0) {
if (errno == ENOMEM) {
SCLogInfo("Memory issue with ring parameters. Retrying.");
continue;
}
SCLogError(SC_ERR_MEM_ALLOC,
"Unable to allocate RX Ring for iface %s: (%d) %s",
devname,
errno,
strerror(errno));
goto socket_err;
} else {
break;
}
}
if (order < 0) {
SCLogError(SC_ERR_MEM_ALLOC,
"Unable to allocate RX Ring for iface %s (order 0 failed)",
devname);
goto socket_err;
}
}
/* Allocate the Ring */
if (ptv->flags & AFP_TPACKET_V3) {
ring_buflen = ptv->req3.tp_block_nr * ptv->req3.tp_block_size;
} else {
ring_buflen = ptv->req.tp_block_nr * ptv->req.tp_block_size;
}
ring_buf = mmap(0, ring_buflen, PROT_READ|PROT_WRITE,
MAP_SHARED, ptv->socket, 0);
if (ring_buf == MAP_FAILED) {
SCLogError(SC_ERR_MEM_ALLOC, "Unable to mmap");
ret = AFPSetupRing(ptv, devname);
if (ret != 0)
goto socket_err;
}
if (ptv->flags & AFP_TPACKET_V3) {
ptv->ring_v3 = SCMalloc(ptv->req3.tp_block_nr * sizeof(*ptv->ring_v3));
if (!ptv->ring_v3) {
SCLogError(SC_ERR_MEM_ALLOC, "Unable to malloc ptv ring_v3");
goto mmap_err;
}
for (i = 0; i < ptv->req3.tp_block_nr; ++i) {
ptv->ring_v3[i].iov_base = ring_buf + (i * ptv->req3.tp_block_size);
ptv->ring_v3[i].iov_len = ptv->req3.tp_block_size;
}
} else {
/* allocate a ring for each frame header pointer*/
ptv->ring_v2 = SCMalloc(ptv->req.tp_frame_nr * sizeof (union thdr *));
if (ptv->ring_v2 == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "Unable to allocate frame buf");
goto mmap_err;
}
memset(ptv->ring_v2, 0, ptv->req.tp_frame_nr * sizeof (union thdr *));
/* fill the header ring with proper frame ptr*/
ptv->frame_offset = 0;
for (i = 0; i < ptv->req.tp_block_nr; ++i) {
void *base = &ring_buf[i * ptv->req.tp_block_size];
unsigned int j;
for (j = 0; j < ptv->req.tp_block_size / ptv->req.tp_frame_size; ++j, ++ptv->frame_offset) {
(((union thdr **)ptv->ring_v2)[ptv->frame_offset]) = base;
base += ptv->req.tp_frame_size;
}
}
ptv->frame_offset = 0;
}
}
SCLogDebug("Using interface '%s' via socket %d", (char *)devname, ptv->socket);
@ -1868,8 +1888,6 @@ frame_err:
if (ptv->ring_v2)
SCFree(ptv->ring_v2);
}
mmap_err:
/* Packet mmap does the cleaning when socket is closed */
socket_err:
close(ptv->socket);
ptv->socket = -1;

Loading…
Cancel
Save