Fix NFQ receive/verdict race condition in cases where the packetpool is empty.

remotes/origin/master-1.0.x
Victor Julien 16 years ago
parent 647b1c0eba
commit bb685751d9

@ -46,16 +46,16 @@ void DecodeTunnel(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt
}
/**
* \brief Get a pseudo packet for tunnels and defrag reassembly. We try to
* get a packet from the packet_q first, but if that is empty we alloc
* a packet that is free'd again after processing.
* \brief Get a packet. We try to get a packet from the packet_q first, but
* if that is empty we alloc a packet that is free'd again after
* processing.
*
* \retval p packet, NULL on error
*/
static Packet *PacketGetPseudoPkt (void)
{
Packet *PacketGetFromQueueOrAlloc(void) {
Packet *p = NULL;
/* try the queue first */
SCMutexLock(&packet_q.mutex_q);
p = PacketDequeue(&packet_q);
SCMutexUnlock(&packet_q.mutex_q);
@ -90,7 +90,7 @@ static Packet *PacketGetPseudoPkt (void)
Packet *PacketPseudoPktSetup(Packet *parent, uint8_t *pkt, uint16_t len, uint8_t proto)
{
/* get us a packet */
Packet *p = PacketGetPseudoPkt();
Packet *p = PacketGetFromQueueOrAlloc();
if (p == NULL) {
return NULL;
}

@ -488,6 +488,7 @@ typedef struct DecodeThreadVars_
void DecodeRegisterPerfCounters(DecodeThreadVars *, ThreadVars *);
Packet *PacketPseudoPktSetup(Packet *parent, uint8_t *pkt, uint16_t len, uint8_t proto);
Packet *PacketGetFromQueueOrAlloc(void);
/* decoder functions */
void DecodeEthernet(ThreadVars *, DecodeThreadVars *, Packet *, uint8_t *, uint16_t, PacketQueue *);

@ -204,7 +204,11 @@ static int NFQCallBack(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
ThreadVars *tv = ntv->tv;
/* grab a packet */
Packet *p = tv->tmqh_in(tv);
Packet *p = PacketGetFromQueueOrAlloc();
if (p == NULL) {
return -1;
}
NFQSetupPkt(p, (void *)nfa);
#ifdef COUNTERS
@ -399,8 +403,7 @@ void NFQRecvPkt(NFQThreadVars *t) {
rv = recv(t->fd, buf, sizeof(buf), 0);
if (rv < 0) {
if (errno == EINTR || errno == EWOULDBLOCK
) {
if (errno == EINTR || errno == EWOULDBLOCK) {
/* no error on timeout */
} else {
#ifdef COUNTERS
@ -497,6 +500,15 @@ process_rv:
TmEcode ReceiveNFQ(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq) {
NFQThreadVars *ntv = (NFQThreadVars *)data;
/* make sure we have at least one packet in the packet pool, to prevent
* us from 1) alloc'ing packets at line rate, 2) have a race condition
* for the nfq mutex lock with the verdict thread. */
SCMutexLock(&packet_q.mutex_q);
if (packet_q.len == 0) {
SCondWait(&packet_q.cond_q, &packet_q.mutex_q);
}
SCMutexUnlock(&packet_q.mutex_q);
/* do our nfq magic */
NFQRecvPkt(ntv);

Loading…
Cancel
Save