This patch makes the drop_early(), calculate_probability() and pie_process_dequeue() functions generic enough to be used by both PIE and FQ-PIE (to be added in a future commit). The major change here is in the way the functions take in arguments. This patch exports these functions and makes FQ-PIE dependent on sch_pie.
Unified · Split
| @@ -124,4 +124,13 @@ static inline void pie_set_enqueue_time(struct sk_buff *skb) · 123 unmodified lines | ||
| 124 | 124 | get_pie_cb(skb)->enqueue_time = psched_get_time(); |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | +bool pie_drop_early(struct Qdisc *sch, struct pie_params *params, | |
| 128 | + struct pie_vars *vars, u32 qlen, u32 packet_size); | |
| 129 | + | |
| 130 | +void pie_process_dequeue(struct sk_buff *skb, struct pie_params *params, | |
| 131 | + struct pie_vars *vars, u32 qlen); | |
| 132 | + | |
| 133 | +void pie_calculate_probability(struct pie_params *params, struct pie_vars *vars, | |
| 134 | + u32 qlen); | |
| 135 | + | |
| 127 | 136 | #endif |
| @@ -30,64 +30,65 @@ struct pie_sched_data { · 29 unmodified lines | ||
| 30 | 30 | struct Qdisc *sch; |
| 31 | 31 | }; |
| 32 | 32 | |
| 33 | −static bool drop_early(struct Qdisc *sch, u32 packet_size) | |
| 33 | +bool pie_drop_early(struct Qdisc *sch, struct pie_params *params, | |
| 34 | + struct pie_vars *vars, u32 qlen, u32 packet_size) | |
| 34 | 35 | { |
| 35 | − struct pie_sched_data *q = qdisc_priv(sch); | |
| 36 | 36 | u64 rnd; |
| 37 | − u64 local_prob = q->vars.prob; | |
| 37 | + u64 local_prob = vars->prob; | |
| 38 | 38 | u32 mtu = psched_mtu(qdisc_dev(sch)); |
| 39 | 39 | |
| 40 | 40 | /* If there is still burst allowance left skip random early drop */ |
| 41 | − if (q->vars.burst_time > 0) | |
| 41 | + if (vars->burst_time > 0) | |
| 42 | 42 | return false; |
| 43 | 43 | |
| 44 | 44 | /* If current delay is less than half of target, and |
| 45 | 45 | * if drop prob is low already, disable early_drop |
| 46 | 46 | */ |
| 47 | − if ((q->vars.qdelay < q->params.target / 2) && | |
| 48 | − (q->vars.prob < MAX_PROB / 5)) | |
| 47 | + if ((vars->qdelay < params->target / 2) && | |
| 48 | + (vars->prob < MAX_PROB / 5)) | |
| 49 | 49 | return false; |
| 50 | 50 | |
| 51 | − /* If we have fewer than 2 mtu-sized packets, disable drop_early, | |
| 51 | + /* If we have fewer than 2 mtu-sized packets, disable pie_drop_early, | |
| 52 | 52 | * similar to min_th in RED |
| 53 | 53 | */ |
| 54 | − if (sch->qstats.backlog < 2 * mtu) | |
| 54 | + if (qlen < 2 * mtu) | |
| 55 | 55 | return false; |
| 56 | 56 | |
| 57 | 57 | /* If bytemode is turned on, use packet size to compute new |
| 58 | 58 | * probablity. Smaller packets will have lower drop prob in this case |
| 59 | 59 | */ |
| 60 | − if (q->params.bytemode && packet_size <= mtu) | |
| 60 | + if (params->bytemode && packet_size <= mtu) | |
| 61 | 61 | local_prob = (u64)packet_size * div_u64(local_prob, mtu); |
| 62 | 62 | else |
| 63 | − local_prob = q->vars.prob; | |
| 63 | + local_prob = vars->prob; | |
| 64 | 64 | |
| 65 | 65 | if (local_prob == 0) { |
| 66 | − q->vars.accu_prob = 0; | |
| 67 | − q->vars.accu_prob_overflows = 0; | |
| 66 | + vars->accu_prob = 0; | |
| 67 | + vars->accu_prob_overflows = 0; | |
| 68 | 68 | } |
| 69 | 69 | |
| 70 | − if (local_prob > MAX_PROB - q->vars.accu_prob) | |
| 71 | − q->vars.accu_prob_overflows++; | |
| 70 | + if (local_prob > MAX_PROB - vars->accu_prob) | |
| 71 | + vars->accu_prob_overflows++; | |
| 72 | 72 | |
| 73 | − q->vars.accu_prob += local_prob; | |
| 73 | + vars->accu_prob += local_prob; | |
| 74 | 74 | |
| 75 | − if (q->vars.accu_prob_overflows == 0 && | |
| 76 | − q->vars.accu_prob < (MAX_PROB / 100) * 85) | |
| 75 | + if (vars->accu_prob_overflows == 0 && | |
| 76 | + vars->accu_prob < (MAX_PROB / 100) * 85) | |
| 77 | 77 | return false; |
| 78 | − if (q->vars.accu_prob_overflows == 8 && | |
| 79 | − q->vars.accu_prob >= MAX_PROB / 2) | |
| 78 | + if (vars->accu_prob_overflows == 8 && | |
| 79 | + vars->accu_prob >= MAX_PROB / 2) | |
| 80 | 80 | return true; |
| 81 | 81 | |
| 82 | 82 | prandom_bytes(&rnd, 8); |
| 83 | 83 | if (rnd < local_prob) { |
| 84 | − q->vars.accu_prob = 0; | |
| 85 | − q->vars.accu_prob_overflows = 0; | |
| 84 | + vars->accu_prob = 0; | |
| 85 | + vars->accu_prob_overflows = 0; | |
| 86 | 86 | return true; |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | 89 | return false; |
| 90 | 90 | } |
| 91 | +EXPORT_SYMBOL_GPL(pie_drop_early); | |
| 91 | 92 | |
| 92 | 93 | static int pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch, |
| 93 | 94 | struct sk_buff **to_free) |
| @@ -100,7 +101,8 @@ static int pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch, · 6 unmodified lines | ||
| 100 | 101 | goto out; |
| 101 | 102 | } |
| 102 | 103 | |
| 103 | − if (!drop_early(sch, skb->len)) { | |
| 104 | + if (!pie_drop_early(sch, &q->params, &q->vars, sch->qstats.backlog, | |
| 105 | + skb->len)) { | |
| 104 | 106 | enqueue = true; |
| 105 | 107 | } else if (q->params.ecn && (q->vars.prob <= MAX_PROB / 10) && |
| 106 | 108 | INET_ECN_set_ce(skb)) { |
| @@ -212,26 +214,25 @@ static int pie_change(struct Qdisc *sch, struct nlattr *opt, · 105 unmodified lines | ||
| 212 | 214 | return 0; |
| 213 | 215 | } |
| 214 | 216 | |
| 215 | −static void pie_process_dequeue(struct Qdisc *sch, struct sk_buff *skb) | |
| 217 | +void pie_process_dequeue(struct sk_buff *skb, struct pie_params *params, | |
| 218 | + struct pie_vars *vars, u32 qlen) | |
| 216 | 219 | { |
| 217 | − struct pie_sched_data *q = qdisc_priv(sch); | |
| 218 | − int qlen = sch->qstats.backlog; /* current queue size in bytes */ | |
| 219 | 220 | psched_time_t now = psched_get_time(); |
| 220 | 221 | u32 dtime = 0; |
| 221 | 222 | |
| 222 | 223 | /* If dq_rate_estimator is disabled, calculate qdelay using the |
| 223 | 224 | * packet timestamp. |
| 224 | 225 | */ |
| 225 | − if (!q->params.dq_rate_estimator) { | |
| 226 | − q->vars.qdelay = now - pie_get_enqueue_time(skb); | |
| 226 | + if (!params->dq_rate_estimator) { | |
| 227 | + vars->qdelay = now - pie_get_enqueue_time(skb); | |
| 227 | 228 | |
| 228 | − if (q->vars.dq_tstamp != DTIME_INVALID) | |
| 229 | − dtime = now - q->vars.dq_tstamp; | |
| 229 | + if (vars->dq_tstamp != DTIME_INVALID) | |
| 230 | + dtime = now - vars->dq_tstamp; | |
| 230 | 231 | |
| 231 | − q->vars.dq_tstamp = now; | |
| 232 | + vars->dq_tstamp = now; | |
| 232 | 233 | |
| 233 | 234 | if (qlen == 0) |
| 234 | − q->vars.qdelay = 0; | |
| 235 | + vars->qdelay = 0; | |
| 235 | 236 | |
| 236 | 237 | if (dtime == 0) |
| 237 | 238 | return; |
| @@ -243,9 +244,9 @@ static void pie_process_dequeue(struct Qdisc *sch, struct sk_buff *skb) · 5 unmodified lines | ||
| 243 | 244 | * we have enough packets to calculate the drain rate. Save |
| 244 | 245 | * current time as dq_tstamp and start measurement cycle. |
| 245 | 246 | */ |
| 246 | − if (qlen >= QUEUE_THRESHOLD && q->vars.dq_count == DQCOUNT_INVALID) { | |
| 247 | − q->vars.dq_tstamp = psched_get_time(); | |
| 248 | − q->vars.dq_count = 0; | |
| 247 | + if (qlen >= QUEUE_THRESHOLD && vars->dq_count == DQCOUNT_INVALID) { | |
| 248 | + vars->dq_tstamp = psched_get_time(); | |
| 249 | + vars->dq_count = 0; | |
| 249 | 250 | } |
| 250 | 251 | |
| 251 | 252 | /* Calculate the average drain rate from this value. If queue length |
| @@ -257,25 +258,25 @@ static void pie_process_dequeue(struct Qdisc *sch, struct sk_buff *skb) · 5 unmodified lines | ||
| 257 | 258 | * in bytes, time difference in psched_time, hence rate is in |
| 258 | 259 | * bytes/psched_time. |
| 259 | 260 | */ |
| 260 | − if (q->vars.dq_count != DQCOUNT_INVALID) { | |
| 261 | − q->vars.dq_count += skb->len; | |
| 261 | + if (vars->dq_count != DQCOUNT_INVALID) { | |
| 262 | + vars->dq_count += skb->len; | |
| 262 | 263 | |
| 263 | − if (q->vars.dq_count >= QUEUE_THRESHOLD) { | |
| 264 | − u32 count = q->vars.dq_count << PIE_SCALE; | |
| 264 | + if (vars->dq_count >= QUEUE_THRESHOLD) { | |
| 265 | + u32 count = vars->dq_count << PIE_SCALE; | |
| 265 | 266 | |
| 266 | − dtime = now - q->vars.dq_tstamp; | |
| 267 | + dtime = now - vars->dq_tstamp; | |
| 267 | 268 | |
| 268 | 269 | if (dtime == 0) |
| 269 | 270 | return; |
| 270 | 271 | |
| 271 | 272 | count = count / dtime; |
| 272 | 273 | |
| 273 | − if (q->vars.avg_dq_rate == 0) | |
| 274 | − q->vars.avg_dq_rate = count; | |
| 274 | + if (vars->avg_dq_rate == 0) | |
| 275 | + vars->avg_dq_rate = count; | |
| 275 | 276 | else |
| 276 | − q->vars.avg_dq_rate = | |
| 277 | − (q->vars.avg_dq_rate - | |
| 278 | − (q->vars.avg_dq_rate >> 3)) + (count >> 3); | |
| 277 | + vars->avg_dq_rate = | |
| 278 | + (vars->avg_dq_rate - | |
| 279 | + (vars->avg_dq_rate >> 3)) + (count >> 3); | |
| 279 | 280 | |
| 280 | 281 | /* If the queue has receded below the threshold, we hold |
| 281 | 282 | * on to the last drain rate calculated, else we reset |
| @@ -283,10 +284,10 @@ static void pie_process_dequeue(struct Qdisc *sch, struct sk_buff *skb) · 1 unmodified line | ||
| 283 | 284 | * packet is dequeued |
| 284 | 285 | */ |
| 285 | 286 | if (qlen < QUEUE_THRESHOLD) { |
| 286 | − q->vars.dq_count = DQCOUNT_INVALID; | |
| 287 | + vars->dq_count = DQCOUNT_INVALID; | |
| 287 | 288 | } else { |
| 288 | − q->vars.dq_count = 0; | |
| 289 | − q->vars.dq_tstamp = psched_get_time(); | |
| 289 | + vars->dq_count = 0; | |
| 290 | + vars->dq_tstamp = psched_get_time(); | |
| 290 | 291 | } |
| 291 | 292 | |
| 292 | 293 | goto burst_allowance_reduction; |
| @@ -296,18 +297,18 @@ static void pie_process_dequeue(struct Qdisc *sch, struct sk_buff *skb) · 3 unmodified lines | ||
| 296 | 297 | return; |
| 297 | 298 | |
| 298 | 299 | burst_allowance_reduction: |
| 299 | − if (q->vars.burst_time > 0) { | |
| 300 | − if (q->vars.burst_time > dtime) | |
| 301 | − q->vars.burst_time -= dtime; | |
| 300 | + if (vars->burst_time > 0) { | |
| 301 | + if (vars->burst_time > dtime) | |
| 302 | + vars->burst_time -= dtime; | |
| 302 | 303 | else |
| 303 | − q->vars.burst_time = 0; | |
| 304 | + vars->burst_time = 0; | |
| 304 | 305 | } |
| 305 | 306 | } |
| 307 | +EXPORT_SYMBOL_GPL(pie_process_dequeue); | |
| 306 | 308 | |
| 307 | −static void calculate_probability(struct Qdisc *sch) | |
| 309 | +void pie_calculate_probability(struct pie_params *params, struct pie_vars *vars, | |
| 310 | + u32 qlen) | |
| 308 | 311 | { |
| 309 | − struct pie_sched_data *q = qdisc_priv(sch); | |
| 310 | − u32 qlen = sch->qstats.backlog; /* queue size in bytes */ | |
| 311 | 312 | psched_time_t qdelay = 0; /* in pschedtime */ |
| 312 | 313 | psched_time_t qdelay_old = 0; /* in pschedtime */ |
| 313 | 314 | s64 delta = 0; /* determines the change in probability */ |
| @@ -316,17 +317,17 @@ static void calculate_probability(struct Qdisc *sch) · 2 unmodified lines | ||
| 316 | 317 | u32 power; |
| 317 | 318 | bool update_prob = true; |
| 318 | 319 | |
| 319 | − if (q->params.dq_rate_estimator) { | |
| 320 | − qdelay_old = q->vars.qdelay; | |
| 321 | − q->vars.qdelay_old = q->vars.qdelay; | |
| 320 | + if (params->dq_rate_estimator) { | |
| 321 | + qdelay_old = vars->qdelay; | |
| 322 | + vars->qdelay_old = vars->qdelay; | |
| 322 | 323 | |
| 323 | − if (q->vars.avg_dq_rate > 0) | |
| 324 | − qdelay = (qlen << PIE_SCALE) / q->vars.avg_dq_rate; | |
| 324 | + if (vars->avg_dq_rate > 0) | |
| 325 | + qdelay = (qlen << PIE_SCALE) / vars->avg_dq_rate; | |
| 325 | 326 | else |
| 326 | 327 | qdelay = 0; |
| 327 | 328 | } else { |
| 328 | − qdelay = q->vars.qdelay; | |
| 329 | − qdelay_old = q->vars.qdelay_old; | |
| 329 | + qdelay = vars->qdelay; | |
| 330 | + qdelay_old = vars->qdelay_old; | |
| 330 | 331 | } |
| 331 | 332 | |
| 332 | 333 | /* If qdelay is zero and qlen is not, it means qlen is very small, |
| @@ -342,18 +343,18 @@ static void calculate_probability(struct Qdisc *sch) · 9 unmodified lines | ||
| 342 | 343 | * probability. alpha/beta are updated locally below by scaling down |
| 343 | 344 | * by 16 to come to 0-2 range. |
| 344 | 345 | */ |
| 345 | − alpha = ((u64)q->params.alpha * (MAX_PROB / PSCHED_TICKS_PER_SEC)) >> 4; | |
| 346 | − beta = ((u64)q->params.beta * (MAX_PROB / PSCHED_TICKS_PER_SEC)) >> 4; | |
| 346 | + alpha = ((u64)params->alpha * (MAX_PROB / PSCHED_TICKS_PER_SEC)) >> 4; | |
| 347 | + beta = ((u64)params->beta * (MAX_PROB / PSCHED_TICKS_PER_SEC)) >> 4; | |
| 347 | 348 | |
| 348 | 349 | /* We scale alpha and beta differently depending on how heavy the |
| 349 | 350 | * congestion is. Please see RFC 8033 for details. |
| 350 | 351 | */ |
| 351 | − if (q->vars.prob < MAX_PROB / 10) { | |
| 352 | + if (vars->prob < MAX_PROB / 10) { | |
| 352 | 353 | alpha >>= 1; |
| 353 | 354 | beta >>= 1; |
| 354 | 355 | |
| 355 | 356 | power = 100; |
| 356 | − while (q->vars.prob < div_u64(MAX_PROB, power) && | |
| 357 | + while (vars->prob < div_u64(MAX_PROB, power) && | |
| 357 | 358 | power <= 1000000) { |
| 358 | 359 | alpha >>= 2; |
| 359 | 360 | beta >>= 2; |
| @@ -362,14 +363,14 @@ static void calculate_probability(struct Qdisc *sch) · 2 unmodified lines | ||
| 362 | 363 | } |
| 363 | 364 | |
| 364 | 365 | /* alpha and beta should be between 0 and 32, in multiples of 1/16 */ |
| 365 | − delta += alpha * (u64)(qdelay - q->params.target); | |
| 366 | + delta += alpha * (u64)(qdelay - params->target); | |
| 366 | 367 | delta += beta * (u64)(qdelay - qdelay_old); |
| 367 | 368 | |
| 368 | − oldprob = q->vars.prob; | |
| 369 | + oldprob = vars->prob; | |
| 369 | 370 | |
| 370 | 371 | /* to ensure we increase probability in steps of no more than 2% */ |
| 371 | 372 | if (delta > (s64)(MAX_PROB / (100 / 2)) && |
| 372 | − q->vars.prob >= MAX_PROB / 10) | |
| 373 | + vars->prob >= MAX_PROB / 10) | |
| 373 | 374 | delta = (MAX_PROB / 100) * 2; |
| 374 | 375 | |
| 375 | 376 | /* Non-linear drop: |
| @@ -380,12 +381,12 @@ static void calculate_probability(struct Qdisc *sch) · 4 unmodified lines | ||
| 380 | 381 | if (qdelay > (PSCHED_NS2TICKS(250 * NSEC_PER_MSEC))) |
| 381 | 382 | delta += MAX_PROB / (100 / 2); |
| 382 | 383 | |
| 383 | − q->vars.prob += delta; | |
| 384 | + vars->prob += delta; | |
| 384 | 385 | |
| 385 | 386 | if (delta > 0) { |
| 386 | 387 | /* prevent overflow */ |
| 387 | − if (q->vars.prob < oldprob) { | |
| 388 | − q->vars.prob = MAX_PROB; | |
| 388 | + if (vars->prob < oldprob) { | |
| 389 | + vars->prob = MAX_PROB; | |
| 389 | 390 | /* Prevent normalization error. If probability is at |
| 390 | 391 | * maximum value already, we normalize it here, and |
| 391 | 392 | * skip the check to do a non-linear drop in the next |
| @@ -395,8 +396,8 @@ static void calculate_probability(struct Qdisc *sch) · 3 unmodified lines | ||
| 395 | 396 | } |
| 396 | 397 | } else { |
| 397 | 398 | /* prevent underflow */ |
| 398 | − if (q->vars.prob > oldprob) | |
| 399 | − q->vars.prob = 0; | |
| 399 | + if (vars->prob > oldprob) | |
| 400 | + vars->prob = 0; | |
| 400 | 401 | } |
| 401 | 402 | |
| 402 | 403 | /* Non-linear drop in probability: Reduce drop probability quickly if |
| @@ -405,10 +406,10 @@ static void calculate_probability(struct Qdisc *sch) · 2 unmodified lines | ||
| 405 | 406 | |
| 406 | 407 | if (qdelay == 0 && qdelay_old == 0 && update_prob) |
| 407 | 408 | /* Reduce drop probability to 98.4% */ |
| 408 | − q->vars.prob -= q->vars.prob / 64u; | |
| 409 | + vars->prob -= vars->prob / 64; | |
| 409 | 410 | |
| 410 | − q->vars.qdelay = qdelay; | |
| 411 | − q->vars.qlen_old = qlen; | |
| 411 | + vars->qdelay = qdelay; | |
| 412 | + vars->qlen_old = qlen; | |
| 412 | 413 | |
| 413 | 414 | /* We restart the measurement cycle if the following conditions are met |
| 414 | 415 | * 1. If the delay has been low for 2 consecutive Tupdate periods |
| @@ -416,16 +417,17 @@ static void calculate_probability(struct Qdisc *sch) · 1 unmodified line | ||
| 416 | 417 | * 3. If average dq_rate_estimator is enabled, we have atleast one |
| 417 | 418 | * estimate for the avg_dq_rate ie., is a non-zero value |
| 418 | 419 | */ |
| 419 | − if ((q->vars.qdelay < q->params.target / 2) && | |
| 420 | − (q->vars.qdelay_old < q->params.target / 2) && | |
| 421 | − q->vars.prob == 0 && | |
| 422 | − (!q->params.dq_rate_estimator || q->vars.avg_dq_rate > 0)) { | |
| 423 | − pie_vars_init(&q->vars); | |
| 420 | + if ((vars->qdelay < params->target / 2) && | |
| 421 | + (vars->qdelay_old < params->target / 2) && | |
| 422 | + vars->prob == 0 && | |
| 423 | + (!params->dq_rate_estimator || vars->avg_dq_rate > 0)) { | |
| 424 | + pie_vars_init(vars); | |
| 424 | 425 | } |
| 425 | 426 | |
| 426 | − if (!q->params.dq_rate_estimator) | |
| 427 | − q->vars.qdelay_old = qdelay; | |
| 427 | + if (!params->dq_rate_estimator) | |
| 428 | + vars->qdelay_old = qdelay; | |
| 428 | 429 | } |
| 430 | +EXPORT_SYMBOL_GPL(pie_calculate_probability); | |
| 429 | 431 | |
| 430 | 432 | static void pie_timer(struct timer_list *t) |
| 431 | 433 | { |
| @@ -434,7 +436,7 @@ static void pie_timer(struct timer_list *t) · 2 unmodified lines | ||
| 434 | 436 | spinlock_t *root_lock = qdisc_lock(qdisc_root_sleeping(sch)); |
| 435 | 437 | |
| 436 | 438 | spin_lock(root_lock); |
| 437 | − calculate_probability(sch); | |
| 439 | + pie_calculate_probability(&q->params, &q->vars, sch->qstats.backlog); | |
| 438 | 440 | |
| 439 | 441 | /* reset the timer to fire after 'tupdate'. tupdate is in jiffies. */ |
| 440 | 442 | if (q->params.tupdate) |
| @@ -523,12 +525,13 @@ static int pie_dump_stats(struct Qdisc *sch, struct gnet_dump *d) · 82 unmodified lines | ||
| 523 | 525 | |
| 524 | 526 | static struct sk_buff *pie_qdisc_dequeue(struct Qdisc *sch) |
| 525 | 527 | { |
| 528 | + struct pie_sched_data *q = qdisc_priv(sch); | |
| 526 | 529 | struct sk_buff *skb = qdisc_dequeue_head(sch); |
| 527 | 530 | |
| 528 | 531 | if (!skb) |
| 529 | 532 | return NULL; |
| 530 | 533 | |
| 531 | − pie_process_dequeue(sch, skb); | |
| 534 | + pie_process_dequeue(skb, &q->params, &q->vars, sch->qstats.backlog); | |
| 532 | 535 | return skb; |
| 533 | 536 | } |
| 534 | 537 | |