forked from mirrors/linux
		
	net_sched: sch_cake: Add drop reasons
Add three qdisc-specific drop reasons and use them in sch_cake:
 1) SKB_DROP_REASON_QDISC_OVERLIMIT
    Whenever the total queue limit for a qdisc instance is exceeded
    and a packet is dropped to make room.
 2) SKB_DROP_REASON_QDISC_CONGESTED
    Whenever a packet is dropped by the qdisc AQM algorithm because
    congestion is detected.
 3) SKB_DROP_REASON_CAKE_FLOOD
    Whenever a packet is dropped by the flood protection part of the
    CAKE AQM algorithm (BLUE).
Also use the existing SKB_DROP_REASON_QUEUE_PURGE in cake_clear_tin().
Reasons show up as:
perf record -a -e skb:kfree_skb sleep 1; perf script
          iperf3     665 [005]   848.656964: skb:kfree_skb: skbaddr=0xffff98168a333500 rx_sk=(nil) protocol=34525 location=__dev_queue_xmit+0x10f0 reason: QDISC_OVERLIMIT
         swapper       0 [001]   909.166055: skb:kfree_skb: skbaddr=0xffff98168280cee0 rx_sk=(nil) protocol=34525 location=cake_dequeue+0x5ef reason: QDISC_CONGESTED
Reviewed-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
Acked-by: Dave Taht <dave.taht@gmail.com>
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Link: https://patch.msgid.link/20241211-cake-drop-reason-v2-1-920afadf4d1b@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
			
			
This commit is contained in:
		
							parent
							
								
									5098462fba
								
							
						
					
					
						commit
						a42d71e322
					
				
					 2 changed files with 41 additions and 20 deletions
				
			
		|  | @ -58,6 +58,9 @@ | ||||||
| 	FN(TC_EGRESS)			\ | 	FN(TC_EGRESS)			\ | ||||||
| 	FN(SECURITY_HOOK)		\ | 	FN(SECURITY_HOOK)		\ | ||||||
| 	FN(QDISC_DROP)			\ | 	FN(QDISC_DROP)			\ | ||||||
|  | 	FN(QDISC_OVERLIMIT)		\ | ||||||
|  | 	FN(QDISC_CONGESTED)		\ | ||||||
|  | 	FN(CAKE_FLOOD)			\ | ||||||
| 	FN(FQ_BAND_LIMIT)		\ | 	FN(FQ_BAND_LIMIT)		\ | ||||||
| 	FN(FQ_HORIZON_LIMIT)		\ | 	FN(FQ_HORIZON_LIMIT)		\ | ||||||
| 	FN(FQ_FLOW_LIMIT)		\ | 	FN(FQ_FLOW_LIMIT)		\ | ||||||
|  | @ -314,6 +317,21 @@ enum skb_drop_reason { | ||||||
| 	 * failed to enqueue to current qdisc) | 	 * failed to enqueue to current qdisc) | ||||||
| 	 */ | 	 */ | ||||||
| 	SKB_DROP_REASON_QDISC_DROP, | 	SKB_DROP_REASON_QDISC_DROP, | ||||||
|  | 	/**
 | ||||||
|  | 	 * @SKB_DROP_REASON_QDISC_OVERLIMIT: dropped by qdisc when a qdisc | ||||||
|  | 	 * instance exceeds its total buffer size limit. | ||||||
|  | 	 */ | ||||||
|  | 	SKB_DROP_REASON_QDISC_OVERLIMIT, | ||||||
|  | 	/**
 | ||||||
|  | 	 * @SKB_DROP_REASON_QDISC_CONGESTED: dropped by a qdisc AQM algorithm | ||||||
|  | 	 * due to congestion. | ||||||
|  | 	 */ | ||||||
|  | 	SKB_DROP_REASON_QDISC_CONGESTED, | ||||||
|  | 	/**
 | ||||||
|  | 	 * @SKB_DROP_REASON_CAKE_FLOOD: dropped by the flood protection part of | ||||||
|  | 	 * CAKE qdisc AQM algorithm (BLUE). | ||||||
|  | 	 */ | ||||||
|  | 	SKB_DROP_REASON_CAKE_FLOOD, | ||||||
| 	/**
 | 	/**
 | ||||||
| 	 * @SKB_DROP_REASON_FQ_BAND_LIMIT: dropped by fq qdisc when per band | 	 * @SKB_DROP_REASON_FQ_BAND_LIMIT: dropped by fq qdisc when per band | ||||||
| 	 * limit is reached. | 	 * limit is reached. | ||||||
|  |  | ||||||
|  | @ -484,13 +484,14 @@ static bool cobalt_queue_empty(struct cobalt_vars *vars, | ||||||
| /* Call this with a freshly dequeued packet for possible congestion marking.
 | /* Call this with a freshly dequeued packet for possible congestion marking.
 | ||||||
|  * Returns true as an instruction to drop the packet, false for delivery. |  * Returns true as an instruction to drop the packet, false for delivery. | ||||||
|  */ |  */ | ||||||
| static bool cobalt_should_drop(struct cobalt_vars *vars, | static enum skb_drop_reason cobalt_should_drop(struct cobalt_vars *vars, | ||||||
| 			       struct cobalt_params *p, | 					       struct cobalt_params *p, | ||||||
| 			       ktime_t now, | 					       ktime_t now, | ||||||
| 			       struct sk_buff *skb, | 					       struct sk_buff *skb, | ||||||
| 			       u32 bulk_flows) | 					       u32 bulk_flows) | ||||||
| { | { | ||||||
| 	bool next_due, over_target, drop = false; | 	enum skb_drop_reason reason = SKB_NOT_DROPPED_YET; | ||||||
|  | 	bool next_due, over_target; | ||||||
| 	ktime_t schedule; | 	ktime_t schedule; | ||||||
| 	u64 sojourn; | 	u64 sojourn; | ||||||
| 
 | 
 | ||||||
|  | @ -533,7 +534,8 @@ static bool cobalt_should_drop(struct cobalt_vars *vars, | ||||||
| 
 | 
 | ||||||
| 	if (next_due && vars->dropping) { | 	if (next_due && vars->dropping) { | ||||||
| 		/* Use ECN mark if possible, otherwise drop */ | 		/* Use ECN mark if possible, otherwise drop */ | ||||||
| 		drop = !(vars->ecn_marked = INET_ECN_set_ce(skb)); | 		if (!(vars->ecn_marked = INET_ECN_set_ce(skb))) | ||||||
|  | 			reason = SKB_DROP_REASON_QDISC_CONGESTED; | ||||||
| 
 | 
 | ||||||
| 		vars->count++; | 		vars->count++; | ||||||
| 		if (!vars->count) | 		if (!vars->count) | ||||||
|  | @ -556,16 +558,17 @@ static bool cobalt_should_drop(struct cobalt_vars *vars, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Simple BLUE implementation.  Lack of ECN is deliberate. */ | 	/* Simple BLUE implementation.  Lack of ECN is deliberate. */ | ||||||
| 	if (vars->p_drop) | 	if (vars->p_drop && reason == SKB_NOT_DROPPED_YET && | ||||||
| 		drop |= (get_random_u32() < vars->p_drop); | 	    get_random_u32() < vars->p_drop) | ||||||
|  | 		reason = SKB_DROP_REASON_CAKE_FLOOD; | ||||||
| 
 | 
 | ||||||
| 	/* Overload the drop_next field as an activity timeout */ | 	/* Overload the drop_next field as an activity timeout */ | ||||||
| 	if (!vars->count) | 	if (!vars->count) | ||||||
| 		vars->drop_next = ktime_add_ns(now, p->interval); | 		vars->drop_next = ktime_add_ns(now, p->interval); | ||||||
| 	else if (ktime_to_ns(schedule) > 0 && !drop) | 	else if (ktime_to_ns(schedule) > 0 && reason == SKB_NOT_DROPPED_YET) | ||||||
| 		vars->drop_next = now; | 		vars->drop_next = now; | ||||||
| 
 | 
 | ||||||
| 	return drop; | 	return reason; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool cake_update_flowkeys(struct flow_keys *keys, | static bool cake_update_flowkeys(struct flow_keys *keys, | ||||||
|  | @ -1528,12 +1531,11 @@ static unsigned int cake_drop(struct Qdisc *sch, struct sk_buff **to_free) | ||||||
| 
 | 
 | ||||||
| 	flow->dropped++; | 	flow->dropped++; | ||||||
| 	b->tin_dropped++; | 	b->tin_dropped++; | ||||||
| 	sch->qstats.drops++; |  | ||||||
| 
 | 
 | ||||||
| 	if (q->rate_flags & CAKE_FLAG_INGRESS) | 	if (q->rate_flags & CAKE_FLAG_INGRESS) | ||||||
| 		cake_advance_shaper(q, b, skb, now, true); | 		cake_advance_shaper(q, b, skb, now, true); | ||||||
| 
 | 
 | ||||||
| 	__qdisc_drop(skb, to_free); | 	qdisc_drop_reason(skb, sch, to_free, SKB_DROP_REASON_QDISC_OVERLIMIT); | ||||||
| 	sch->q.qlen--; | 	sch->q.qlen--; | ||||||
| 	qdisc_tree_reduce_backlog(sch, 1, len); | 	qdisc_tree_reduce_backlog(sch, 1, len); | ||||||
| 
 | 
 | ||||||
|  | @ -1926,7 +1928,7 @@ static void cake_clear_tin(struct Qdisc *sch, u16 tin) | ||||||
| 	q->cur_tin = tin; | 	q->cur_tin = tin; | ||||||
| 	for (q->cur_flow = 0; q->cur_flow < CAKE_QUEUES; q->cur_flow++) | 	for (q->cur_flow = 0; q->cur_flow < CAKE_QUEUES; q->cur_flow++) | ||||||
| 		while (!!(skb = cake_dequeue_one(sch))) | 		while (!!(skb = cake_dequeue_one(sch))) | ||||||
| 			kfree_skb(skb); | 			kfree_skb_reason(skb, SKB_DROP_REASON_QUEUE_PURGE); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static struct sk_buff *cake_dequeue(struct Qdisc *sch) | static struct sk_buff *cake_dequeue(struct Qdisc *sch) | ||||||
|  | @ -1934,6 +1936,7 @@ static struct sk_buff *cake_dequeue(struct Qdisc *sch) | ||||||
| 	struct cake_sched_data *q = qdisc_priv(sch); | 	struct cake_sched_data *q = qdisc_priv(sch); | ||||||
| 	struct cake_tin_data *b = &q->tins[q->cur_tin]; | 	struct cake_tin_data *b = &q->tins[q->cur_tin]; | ||||||
| 	struct cake_host *srchost, *dsthost; | 	struct cake_host *srchost, *dsthost; | ||||||
|  | 	enum skb_drop_reason reason; | ||||||
| 	ktime_t now = ktime_get(); | 	ktime_t now = ktime_get(); | ||||||
| 	struct cake_flow *flow; | 	struct cake_flow *flow; | ||||||
| 	struct list_head *head; | 	struct list_head *head; | ||||||
|  | @ -2143,12 +2146,12 @@ static struct sk_buff *cake_dequeue(struct Qdisc *sch) | ||||||
| 			goto begin; | 			goto begin; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		reason = cobalt_should_drop(&flow->cvars, &b->cparams, now, skb, | ||||||
|  | 					    (b->bulk_flow_count * | ||||||
|  | 					     !!(q->rate_flags & | ||||||
|  | 						CAKE_FLAG_INGRESS))); | ||||||
| 		/* Last packet in queue may be marked, shouldn't be dropped */ | 		/* Last packet in queue may be marked, shouldn't be dropped */ | ||||||
| 		if (!cobalt_should_drop(&flow->cvars, &b->cparams, now, skb, | 		if (reason == SKB_NOT_DROPPED_YET || !flow->head) | ||||||
| 					(b->bulk_flow_count * |  | ||||||
| 					 !!(q->rate_flags & |  | ||||||
| 					    CAKE_FLAG_INGRESS))) || |  | ||||||
| 		    !flow->head) |  | ||||||
| 			break; | 			break; | ||||||
| 
 | 
 | ||||||
| 		/* drop this packet, get another one */ | 		/* drop this packet, get another one */ | ||||||
|  | @ -2162,7 +2165,7 @@ static struct sk_buff *cake_dequeue(struct Qdisc *sch) | ||||||
| 		b->tin_dropped++; | 		b->tin_dropped++; | ||||||
| 		qdisc_tree_reduce_backlog(sch, 1, qdisc_pkt_len(skb)); | 		qdisc_tree_reduce_backlog(sch, 1, qdisc_pkt_len(skb)); | ||||||
| 		qdisc_qstats_drop(sch); | 		qdisc_qstats_drop(sch); | ||||||
| 		kfree_skb(skb); | 		kfree_skb_reason(skb, reason); | ||||||
| 		if (q->rate_flags & CAKE_FLAG_INGRESS) | 		if (q->rate_flags & CAKE_FLAG_INGRESS) | ||||||
| 			goto retry; | 			goto retry; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Toke Høiland-Jørgensen
						Toke Høiland-Jørgensen