* set a token bucket regulator. * if the specified rate is zero, the token bucket regulator is deleted. */
(ifq, profile)
| 325 | * if the specified rate is zero, the token bucket regulator is deleted. |
| 326 | */ |
| 327 | int |
| 328 | tbr_set(ifq, profile) |
| 329 | struct ifaltq *ifq; |
| 330 | struct tb_profile *profile; |
| 331 | { |
| 332 | struct tb_regulator *tbr, *otbr; |
| 333 | |
| 334 | if (tbr_dequeue_ptr == NULL) |
| 335 | tbr_dequeue_ptr = tbr_dequeue; |
| 336 | |
| 337 | if (machclk_freq == 0) |
| 338 | init_machclk(); |
| 339 | if (machclk_freq == 0) { |
| 340 | printf("tbr_set: no cpu clock available!\n"); |
| 341 | return (ENXIO); |
| 342 | } |
| 343 | |
| 344 | IFQ_LOCK(ifq); |
| 345 | if (profile->rate == 0) { |
| 346 | /* delete this tbr */ |
| 347 | if ((tbr = ifq->altq_tbr) == NULL) { |
| 348 | IFQ_UNLOCK(ifq); |
| 349 | return (ENOENT); |
| 350 | } |
| 351 | ifq->altq_tbr = NULL; |
| 352 | free(tbr, M_DEVBUF); |
| 353 | IFQ_UNLOCK(ifq); |
| 354 | return (0); |
| 355 | } |
| 356 | |
| 357 | tbr = malloc(sizeof(struct tb_regulator), M_DEVBUF, M_NOWAIT | M_ZERO); |
| 358 | if (tbr == NULL) { |
| 359 | IFQ_UNLOCK(ifq); |
| 360 | return (ENOMEM); |
| 361 | } |
| 362 | |
| 363 | tbr->tbr_rate = TBR_SCALE(profile->rate / 8) / machclk_freq; |
| 364 | tbr->tbr_depth = TBR_SCALE(profile->depth); |
| 365 | if (tbr->tbr_rate > 0) |
| 366 | tbr->tbr_filluptime = tbr->tbr_depth / tbr->tbr_rate; |
| 367 | else |
| 368 | tbr->tbr_filluptime = LLONG_MAX; |
| 369 | /* |
| 370 | * The longest time between tbr_dequeue() calls will be about 1 |
| 371 | * system tick, as the callout that drives it is scheduled once per |
| 372 | * tick. The refill-time detection logic in tbr_dequeue() can only |
| 373 | * properly detect the passage of up to LLONG_MAX machclk ticks. |
| 374 | * Therefore, in order for this logic to function properly in the |
| 375 | * extreme case, the maximum value of tbr_filluptime should be |
| 376 | * LLONG_MAX less one system tick's worth of machclk ticks less |
| 377 | * some additional slop factor (here one more system tick's worth |
| 378 | * of machclk ticks). |
| 379 | */ |
| 380 | if (tbr->tbr_filluptime > (LLONG_MAX - 2 * machclk_per_tick)) |
| 381 | tbr->tbr_filluptime = LLONG_MAX - 2 * machclk_per_tick; |
| 382 | tbr->tbr_token = tbr->tbr_depth; |
| 383 | tbr->tbr_last = read_machclk(); |
| 384 | tbr->tbr_lastop = ALTDQ_REMOVE; |
no test coverage detected