void TmqhOutputPacketpool(ThreadVars *t, Packet *p) { bool proot = false; SCEnter(); SCLogDebug("Packet %p, p->root %p, alloced %s", p, p->root, p->flags & PKT_ALLOC ? "true" : "false"); if (IS_TUNNEL_PKT(p)) { SCLogDebug("Packet %p is a tunnel packet: %s", p,p->root ? "upper layer" : "tunnel root"); /* get a lock to access root packet fields */ SCMutex *m = p->root ? &p->root->tunnel_mutex : &p->tunnel_mutex; SCMutexLock(m); if (IS_TUNNEL_ROOT_PKT(p)) { SCLogDebug("IS_TUNNEL_ROOT_PKT == TRUE"); const uint16_t outstanding = TUNNEL_PKT_TPR(p) - TUNNEL_PKT_RTV(p); SCLogDebug("root pkt: outstanding %u", outstanding); if (outstanding == 0) { SCLogDebug("no tunnel packets outstanding, no more tunnel " "packet(s) depending on this root"); /* if this packet is the root and there are no * more tunnel packets to consider * * return it to the pool */ } else { SCLogDebug("tunnel root Packet %p: outstanding > 0, so " "packets are still depending on this root, setting " "SET_TUNNEL_PKT_VERDICTED", p); /* if this is the root and there are more tunnel * packets, return this to the pool. It's still referenced * by the tunnel packets, and we will return it * when we handle them */ SET_TUNNEL_PKT_VERDICTED(p); PACKET_PROFILING_END(p); SCMutexUnlock(m); SCReturn; } } else { SCLogDebug("NOT IS_TUNNEL_ROOT_PKT, so tunnel pkt"); TUNNEL_INCR_PKT_RTV_NOLOCK(p); const uint16_t outstanding = TUNNEL_PKT_TPR(p) - TUNNEL_PKT_RTV(p); SCLogDebug("tunnel pkt: outstanding %u", outstanding); /* all tunnel packets are processed except us. Root already * processed. So return tunnel pkt and root packet to the * pool. */ if (outstanding == 0 && p->root && IS_TUNNEL_PKT_VERDICTED(p->root)) { SCLogDebug("root verdicted == true && no outstanding"); /* handle freeing the root as well*/ SCLogDebug("setting proot = 1 for root pkt, p->root %p " "(tunnel packet %p)", p->root, p); proot = true; /* fall through */ } else { /* root not ready yet, or not the last tunnel packet, * so get rid of the tunnel pkt only */ SCLogDebug("NOT IS_TUNNEL_PKT_VERDICTED (%s) || " "outstanding > 0 (%u)", (p->root && IS_TUNNEL_PKT_VERDICTED(p->root)) ? "true" : "false", outstanding); /* fall through */ } } SCMutexUnlock(m); SCLogDebug("tunnel stuff done, move on (proot %d)", proot); } /* we're done with the tunnel root now as well */ if (proot == true) { SCLogDebug("getting rid of root pkt... alloc'd %s", p->root->flags & PKT_ALLOC ? "true" : "false"); PACKET_RELEASE_REFS(p->root); p->root->ReleasePacket(p->root); p->root = NULL; } PACKET_PROFILING_END(p); PACKET_RELEASE_REFS(p); p->ReleasePacket(p); SCReturn; }
void TmqhOutputPacketpool(ThreadVars *t, Packet *p) { int proot = 0; SCEnter(); SCLogDebug("Packet %p, p->root %p, alloced %s", p, p->root, p->flags & PKT_ALLOC ? "true" : "false"); /** \todo make this a callback * Release tcp segments. Done here after alerting can use them. */ if (p->flow != NULL && p->proto == IPPROTO_TCP) { SCMutexLock(&p->flow->m); StreamTcpPruneSession(p->flow, p->flowflags & FLOW_PKT_TOSERVER ? STREAM_TOSERVER : STREAM_TOCLIENT); SCMutexUnlock(&p->flow->m); } if (IS_TUNNEL_PKT(p)) { SCLogDebug("Packet %p is a tunnel packet: %s", p,p->root ? "upper layer" : "tunnel root"); /* get a lock to access root packet fields */ SCMutex *m = p->root ? &p->root->tunnel_mutex : &p->tunnel_mutex; SCMutexLock(m); if (IS_TUNNEL_ROOT_PKT(p)) { SCLogDebug("IS_TUNNEL_ROOT_PKT == TRUE"); if (TUNNEL_PKT_TPR(p) == 0) { SCLogDebug("TUNNEL_PKT_TPR(p) == 0, no more tunnel packet " "depending on this root"); /* if this packet is the root and there are no * more tunnel packets, return it to the pool */ /* fall through */ } else { SCLogDebug("tunnel root Packet %p: TUNNEL_PKT_TPR(p) > 0, so " "packets are still depending on this root, setting " "p->tunnel_verdicted == 1", p); /* if this is the root and there are more tunnel * packets, return this to the pool. It's still referenced * by the tunnel packets, and we will return it * when we handle them */ SET_TUNNEL_PKT_VERDICTED(p); SCMutexUnlock(m); PACKET_PROFILING_END(p); SCReturn; } } else { SCLogDebug("NOT IS_TUNNEL_ROOT_PKT, so tunnel pkt"); /* the p->root != NULL here seems unnecessary: IS_TUNNEL_PKT checks * that p->tunnel_pkt == 1, IS_TUNNEL_ROOT_PKT checks that + * p->root == NULL. So when we are here p->root can only be * non-NULL, right? CLANG thinks differently. May be a FP, but * better safe than sorry. VJ */ if (p->root != NULL && IS_TUNNEL_PKT_VERDICTED(p->root) && TUNNEL_PKT_TPR(p) == 1) { SCLogDebug("p->root->tunnel_verdicted == 1 && TUNNEL_PKT_TPR(p) == 1"); /* the root is ready and we are the last tunnel packet, * lets enqueue them both. */ TUNNEL_DECR_PKT_TPR_NOLOCK(p); /* handle the root */ SCLogDebug("setting proot = 1 for root pkt, p->root %p " "(tunnel packet %p)", p->root, p); proot = 1; /* fall through */ } else { /* root not ready yet, so get rid of the tunnel pkt only */ SCLogDebug("NOT p->root->tunnel_verdicted == 1 && " "TUNNEL_PKT_TPR(p) == 1 (%" PRIu32 ")", TUNNEL_PKT_TPR(p)); TUNNEL_DECR_PKT_TPR_NOLOCK(p); /* fall through */ } } SCMutexUnlock(m); SCLogDebug("tunnel stuff done, move on (proot %d)", proot); } FlowDeReference(&p->flow); /* we're done with the tunnel root now as well */ if (proot == 1) { SCLogDebug("getting rid of root pkt... alloc'd %s", p->root->flags & PKT_ALLOC ? "true" : "false"); FlowDeReference(&p->root->flow); /* if p->root uses extended data, free them */ if (p->root->ext_pkt) { if (!(p->root->flags & PKT_ZERO_COPY)) { SCFree(p->root->ext_pkt); } p->root->ext_pkt = NULL; } p->root->ReleasePacket(p->root); p->root = NULL; } /* if p uses extended data, free them */ if (p->ext_pkt) { if (!(p->flags & PKT_ZERO_COPY)) { SCFree(p->ext_pkt); } p->ext_pkt = NULL; } PACKET_PROFILING_END(p); p->ReleasePacket(p); SCReturn; }