+
+static int
+fq_compressor(fq_if_t *fqs, fq_t *fq, fq_if_classq_t *fq_cl,
+ pktsched_pkt_t *pkt)
+{
+ classq_pkt_type_t ptype = fq->fq_ptype;
+ uint32_t comp_gencnt = 0;
+ uint64_t *pkt_timestamp;
+ uint64_t old_timestamp = 0;
+ uint32_t old_pktlen = 0;
+ struct ifclassq *ifq = fqs->fqs_ifq;
+
+ if (__improbable(!tcp_do_ack_compression)) {
+ return 0;
+ }
+
+ pktsched_get_pkt_vars(pkt, NULL, &pkt_timestamp, NULL, NULL, NULL,
+ &comp_gencnt);
+
+ if (comp_gencnt == 0) {
+ return 0;
+ }
+
+ fq_cl->fcl_stat.fcl_pkts_compressible++;
+
+ if (fq_empty(fq)) {
+ return 0;
+ }
+
+ if (ptype == QP_MBUF) {
+ struct mbuf *m = MBUFQ_LAST(&fq->fq_mbufq);
+
+ if (comp_gencnt != m->m_pkthdr.comp_gencnt) {
+ return 0;
+ }
+
+ /* If we got until here, we should merge/replace the segment */
+ MBUFQ_REMOVE(&fq->fq_mbufq, m);
+ old_pktlen = m_pktlen(m);
+ old_timestamp = m->m_pkthdr.pkt_timestamp;
+
+ IFCQ_CONVERT_LOCK(fqs->fqs_ifq);
+ m_freem(m);
+ }
+
+ fq->fq_bytes -= old_pktlen;
+ fq_cl->fcl_stat.fcl_byte_cnt -= old_pktlen;
+ fq_cl->fcl_stat.fcl_pkt_cnt--;
+ IFCQ_DEC_LEN(ifq);
+ IFCQ_DEC_BYTES(ifq, old_pktlen);
+
+ *pkt_timestamp = old_timestamp;
+
+ return CLASSQEQ_COMPRESSED;
+}
+