FN(GENERIC) \
FN(OVERLIMIT) \
FN(CONGESTED) \
+ FN(MAXFLOWS) \
FN(CAKE_FLOOD) \
FN(FQ_BAND_LIMIT) \
FN(FQ_HORIZON_LIMIT) \
- FN(FQ_FLOW_LIMIT) \
+ FN(FLOW_LIMIT) \
FNe(MAX)
#undef FN
* congestion to the sender and prevent bufferbloat.
*/
QDISC_DROP_CONGESTED,
+ /**
+ * @QDISC_DROP_MAXFLOWS: packet dropped because the qdisc's flow
+ * tracking table is full and no free slots are available to allocate
+ * for a new flow. This indicates flow table exhaustion in flow-based
+ * qdiscs that maintain per-flow state (e.g., SFQ).
+ */
+ QDISC_DROP_MAXFLOWS,
/**
* @QDISC_DROP_CAKE_FLOOD: CAKE qdisc dropped packet due to flood
* protection mechanism (BLUE algorithm). This indicates potential
*/
QDISC_DROP_FQ_HORIZON_LIMIT,
/**
- * @QDISC_DROP_FQ_FLOW_LIMIT: FQ dropped packet because an individual
- * flow exceeded its per-flow packet limit.
+ * @QDISC_DROP_FLOW_LIMIT: packet dropped because an individual flow
+ * exceeded its per-flow packet/depth limit. Used by FQ and SFQ qdiscs
+ * to enforce per-flow fairness and prevent a single flow from
+ * monopolizing queue resources.
*/
- QDISC_DROP_FQ_FLOW_LIMIT,
+ QDISC_DROP_FLOW_LIMIT,
/**
* @QDISC_DROP_MAX: the maximum of qdisc drop reasons, which
* shouldn't be used as a real 'reason' - only for tracing code gen
if (unlikely(f->qlen >= q->flow_plimit)) {
q->stat_flows_plimit++;
return qdisc_drop_reason(skb, sch, to_free,
- QDISC_DROP_FQ_FLOW_LIMIT);
+ QDISC_DROP_FLOW_LIMIT);
}
if (fq_flow_is_detached(f)) {
sfq_dec(q, x);
sch->q.qlen--;
qdisc_qstats_backlog_dec(sch, skb);
- qdisc_drop(skb, sch, to_free);
+ qdisc_drop_reason(skb, sch, to_free, QDISC_DROP_OVERLIMIT);
return len;
}
if (x == SFQ_EMPTY_SLOT) {
x = q->dep[0].next; /* get a free slot */
if (x >= SFQ_MAX_FLOWS)
- return qdisc_drop(skb, sch, to_free);
+ return qdisc_drop_reason(skb, sch, to_free, QDISC_DROP_MAXFLOWS);
q->ht[hash] = x;
slot = &q->slots[x];
slot->hash = hash;
if (slot->qlen >= q->maxdepth) {
congestion_drop:
if (!sfq_headdrop(q))
- return qdisc_drop(skb, sch, to_free);
+ return qdisc_drop_reason(skb, sch, to_free, QDISC_DROP_FLOW_LIMIT);
/* We know we have at least one packet in queue */
head = slot_dequeue_head(slot);
delta = qdisc_pkt_len(head) - qdisc_pkt_len(skb);
sch->qstats.backlog -= delta;
slot->backlog -= delta;
- qdisc_drop(head, sch, to_free);
+ qdisc_drop_reason(head, sch, to_free, QDISC_DROP_FLOW_LIMIT);
slot_queue_add(slot, skb);
qdisc_tree_reduce_backlog(sch, 0, delta);