mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-08-12 13:22:28 +00:00
rate-limiter: implement hypervisor-built-in rate limiter
As for hypervisors that support built-in rate limiter, like firecracker, we use this built-in characteristics to implement rate limiter in kata. kata-defined rate is in bits with scaling factors of 1000, otherwise fc-defined rate is in bytes with scaling factors of 1024, so need reversion. Fixes: #250 Signed-off-by: Penny Zheng <penny.zheng@arm.com>
This commit is contained in:
parent
676ad989d7
commit
cfeb966763
@ -908,11 +908,52 @@ func (fc *firecracker) fcAddNetDevice(endpoint Endpoint) {
|
|||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
ifaceID := endpoint.Name()
|
ifaceID := endpoint.Name()
|
||||||
|
|
||||||
|
// The implementation of rate limiter is based on TBF.
|
||||||
|
// Rate Limiter defines a token bucket with a maximum capacity (size) to store tokens, and an interval for refilling purposes (refill_time).
|
||||||
|
// The refill-rate is derived from size and refill_time, and it is the constant rate at which the tokens replenish.
|
||||||
|
refillTime := uint64(1000)
|
||||||
|
var rxRateLimiter models.RateLimiter
|
||||||
|
rxSize := fc.config.RxRateLimiterMaxRate
|
||||||
|
if rxSize > 0 {
|
||||||
|
fc.Logger().Info("Add rx rate limiter")
|
||||||
|
|
||||||
|
// kata-defined rxSize is in bits with scaling factors of 1000, but firecracker-defined
|
||||||
|
// rxSize is in bytes with scaling factors of 1024, need reversion.
|
||||||
|
rxSize = revertBytes(rxSize / 8)
|
||||||
|
rxTokenBucket := models.TokenBucket{
|
||||||
|
RefillTime: &refillTime,
|
||||||
|
Size: &rxSize,
|
||||||
|
}
|
||||||
|
rxRateLimiter = models.RateLimiter{
|
||||||
|
Bandwidth: &rxTokenBucket,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var txRateLimiter models.RateLimiter
|
||||||
|
txSize := fc.config.TxRateLimiterMaxRate
|
||||||
|
if txSize > 0 {
|
||||||
|
fc.Logger().Info("Add tx rate limiter")
|
||||||
|
|
||||||
|
// kata-defined txSize is in bits with scaling factors of 1000, but firecracker-defined
|
||||||
|
// txSize is in bytes with scaling factors of 1024, need reversion.
|
||||||
|
txSize = revertBytes(txSize / 8)
|
||||||
|
txTokenBucket := models.TokenBucket{
|
||||||
|
RefillTime: &refillTime,
|
||||||
|
Size: &txSize,
|
||||||
|
}
|
||||||
|
txRateLimiter = models.RateLimiter{
|
||||||
|
Bandwidth: &txTokenBucket,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ifaceCfg := &models.NetworkInterface{
|
ifaceCfg := &models.NetworkInterface{
|
||||||
AllowMmdsRequests: false,
|
AllowMmdsRequests: false,
|
||||||
GuestMac: endpoint.HardwareAddr(),
|
GuestMac: endpoint.HardwareAddr(),
|
||||||
IfaceID: &ifaceID,
|
IfaceID: &ifaceID,
|
||||||
HostDevName: &endpoint.NetworkPair().TapInterface.TAPIface.Name,
|
HostDevName: &endpoint.NetworkPair().TapInterface.TAPIface.Name,
|
||||||
|
RxRateLimiter: &rxRateLimiter,
|
||||||
|
TxRateLimiter: &txRateLimiter,
|
||||||
}
|
}
|
||||||
|
|
||||||
fc.fcConfig.NetworkInterfaces = append(fc.fcConfig.NetworkInterfaces, ifaceCfg)
|
fc.fcConfig.NetworkInterfaces = append(fc.fcConfig.NetworkInterfaces, ifaceCfg)
|
||||||
@ -1216,3 +1257,16 @@ func (fc *firecracker) watchConsole() (*os.File, error) {
|
|||||||
func (fc *firecracker) isRateLimiterBuiltin() bool {
|
func (fc *firecracker) isRateLimiterBuiltin() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In firecracker, it accepts the size of rate limiter in scaling factors of 2^10(1024)
|
||||||
|
// But in kata-defined rate limiter, for better Human-readability, we prefer scaling factors of 10^3(1000).
|
||||||
|
// func revertByte reverts num from scaling factors of 1000 to 1024, e.g. 10000000(10MB) to 10485760.
|
||||||
|
func revertBytes(num uint64) uint64 {
|
||||||
|
a := num / 1000
|
||||||
|
b := num % 1000
|
||||||
|
if a == 0 {
|
||||||
|
return num
|
||||||
|
} else {
|
||||||
|
return 1024*revertBytes(a) + b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -45,3 +45,14 @@ func TestFCTruncateID(t *testing.T) {
|
|||||||
id = fc.truncateID(testShortID)
|
id = fc.truncateID(testShortID)
|
||||||
assert.Equal(expectedID, id)
|
assert.Equal(expectedID, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRevertBytes(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
//10MB
|
||||||
|
testNum := uint64(10000000)
|
||||||
|
expectedNum := uint64(10485760)
|
||||||
|
|
||||||
|
num := revertBytes(testNum)
|
||||||
|
assert.Equal(expectedNum, num)
|
||||||
|
}
|
||||||
|
@ -19,17 +19,17 @@ type TokenBucket struct {
|
|||||||
|
|
||||||
// The initial size of a token bucket.
|
// The initial size of a token bucket.
|
||||||
// Minimum: 0
|
// Minimum: 0
|
||||||
OneTimeBurst *int64 `json:"one_time_burst,omitempty"`
|
OneTimeBurst *uint64 `json:"one_time_burst,omitempty"`
|
||||||
|
|
||||||
// The amount of milliseconds it takes for the bucket to refill.
|
// The amount of milliseconds it takes for the bucket to refill.
|
||||||
// Required: true
|
// Required: true
|
||||||
// Minimum: 0
|
// Minimum: 0
|
||||||
RefillTime *int64 `json:"refill_time"`
|
RefillTime *uint64 `json:"refill_time"`
|
||||||
|
|
||||||
// The total number of tokens this bucket can hold.
|
// The total number of tokens this bucket can hold.
|
||||||
// Required: true
|
// Required: true
|
||||||
// Minimum: 0
|
// Minimum: 0
|
||||||
Size *int64 `json:"size"`
|
Size *uint64 `json:"size"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates this token bucket
|
// Validate validates this token bucket
|
||||||
|
@ -615,17 +615,17 @@ definitions:
|
|||||||
properties:
|
properties:
|
||||||
size:
|
size:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: uint64
|
||||||
description: The total number of tokens this bucket can hold.
|
description: The total number of tokens this bucket can hold.
|
||||||
minimum: 0
|
minimum: 0
|
||||||
one_time_burst:
|
one_time_burst:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: uint64
|
||||||
description: The initial size of a token bucket.
|
description: The initial size of a token bucket.
|
||||||
minimum: 0
|
minimum: 0
|
||||||
refill_time:
|
refill_time:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: uint64
|
||||||
description: The amount of milliseconds it takes for the bucket to refill.
|
description: The amount of milliseconds it takes for the bucket to refill.
|
||||||
minimum: 0
|
minimum: 0
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user