- if (SFB_QUEUE_DELAYBASED(sp) &&
- droptype == DTYPE_NODROP &&
- qlen(q) >= SFB_QUEUE_DELAYBASED_MAXSIZE) {
- droptype = DTYPE_FORCED;
- sp->sfb_stats.drop_queue++;
+ if (droptype == DTYPE_NODROP && qlen(q) >= maxqsize) {
+ if (pkt->pkt_proto == IPPROTO_TCP &&
+ ((pkt->pkt_flags & PKTF_TCP_REXMT) ||
+ (sp->sfb_flags & SFBF_LAST_PKT_DROPPED))) {
+ /*
+ * At some level, dropping packets will make the
+ * flows backoff and will keep memory requirements
+ * under control. But we should not cause a tail
+ * drop because it can take a long time for a
+ * TCP flow to recover. We should try to drop
+ * alternate packets instead.
+ */
+ sp->sfb_flags &= ~SFBF_LAST_PKT_DROPPED;
+ } else {
+ droptype = DTYPE_FORCED;
+ sp->sfb_stats.drop_queue++;
+ sp->sfb_flags |= SFBF_LAST_PKT_DROPPED;
+ }