|
14 | 14 | package v1alpha1
|
15 | 15 |
|
16 | 16 | import (
|
| 17 | + "errors" |
17 | 18 | "strconv"
|
| 19 | + "strings" |
18 | 20 | "time"
|
19 | 21 |
|
20 | 22 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
@@ -47,6 +49,9 @@ const (
|
47 | 49 |
|
48 | 50 | // PartitionAction represents the chaos action of network partition of pods.
|
49 | 51 | PartitionAction NetworkChaosAction = "partition"
|
| 52 | + |
| 53 | + // BandwidthAction represents the chaos action of network bandwidth of pods. |
| 54 | + BandwidthAction NetworkChaosAction = "bandwidth" |
50 | 55 | )
|
51 | 56 |
|
52 | 57 | // PartitionDirection represents the block direction from source to target
|
@@ -133,6 +138,10 @@ type NetworkChaosSpec struct {
|
133 | 138 | // Corrupt represents the detail about corrupt action
|
134 | 139 | Corrupt *CorruptSpec `json:"corrupt,omitempty"`
|
135 | 140 |
|
| 141 | + // Bandwidth represents the detail about bandwidth control action |
| 142 | + // +optional |
| 143 | + Bandwidth *BandwidthSpec `json:"bandwidth,omitempty"` |
| 144 | + |
136 | 145 | // Direction represents the partition direction
|
137 | 146 | // +optional
|
138 | 147 | Direction PartitionDirection `json:"direction"`
|
@@ -369,6 +378,83 @@ func (corrupt *CorruptSpec) ToNetem() (*chaosdaemonpb.Netem, error) {
|
369 | 378 | }, nil
|
370 | 379 | }
|
371 | 380 |
|
| 381 | +// BandwidthSpec defines detail of bandwidth limit. |
| 382 | +type BandwidthSpec struct { |
| 383 | + // Rate is the speed knob. Allows bps, kbps, mbps, gbps, tbps unit. bps means bytes per second. |
| 384 | + Rate string `json:"rate"` |
| 385 | + // Limit is the number of bytes that can be queued waiting for tokens to become available. |
| 386 | + // +kubebuilder:validation:Minimum=1 |
| 387 | + Limit uint32 `json:"limit"` |
| 388 | + // Buffer is the maximum amount of bytes that tokens can be available for instantaneously. |
| 389 | + // +kubebuilder:validation:Minimum=1 |
| 390 | + Buffer uint32 `json:"buffer"` |
| 391 | + // Peakrate is the maximum depletion rate of the bucket. |
| 392 | + // The peakrate does not need to be set, it is only necessary |
| 393 | + // if perfect millisecond timescale shaping is required. |
| 394 | + // +optional |
| 395 | + Peakrate *uint64 `json:"peakrate,omitempty"` |
| 396 | + // Minburst specifies the size of the peakrate bucket. For perfect |
| 397 | + // accuracy, should be set to the MTU of the interface. If a |
| 398 | + // peakrate is needed, but some burstiness is acceptable, this |
| 399 | + // size can be raised. A 3000 byte minburst allows around 3mbit/s |
| 400 | + // of peakrate, given 1000 byte packets. |
| 401 | + // +optional |
| 402 | + Minburst *uint32 `json:"minburst,omitempty"` |
| 403 | +} |
| 404 | + |
| 405 | +// ToTbf converts BandwidthSpec to *chaosdaemonpb.Tbf |
| 406 | +// Bandwidth action use TBF under the hood. |
| 407 | +// TBF stands for Token Bucket Filter, is a classful queueing discipline available |
| 408 | +// for traffic control with the tc command. |
| 409 | +// http://man7.org/linux/man-pages/man8/tc-tbf.8.html |
| 410 | +func (spec *BandwidthSpec) ToTbf() (*chaosdaemonpb.Tbf, error) { |
| 411 | + rate, err := convertUnitToBytes(spec.Rate) |
| 412 | + |
| 413 | + if err != nil { |
| 414 | + return nil, err |
| 415 | + } |
| 416 | + |
| 417 | + tbf := &chaosdaemonpb.Tbf{ |
| 418 | + Rate: rate, |
| 419 | + Limit: spec.Limit, |
| 420 | + Buffer: spec.Buffer, |
| 421 | + } |
| 422 | + |
| 423 | + if spec.Peakrate != nil && spec.Minburst != nil { |
| 424 | + tbf.PeakRate = *spec.Peakrate |
| 425 | + tbf.MinBurst = *spec.Minburst |
| 426 | + } |
| 427 | + |
| 428 | + return tbf, nil |
| 429 | +} |
| 430 | + |
| 431 | +func convertUnitToBytes(nu string) (uint64, error) { |
| 432 | + // normalize input |
| 433 | + s := strings.ToLower(strings.TrimSpace(nu)) |
| 434 | + |
| 435 | + for i, u := range []string{"tbps", "gbps", "mbps", "kbps", "bps"} { |
| 436 | + if strings.HasSuffix(s, u) { |
| 437 | + ts := strings.TrimSuffix(s, u) |
| 438 | + s := strings.TrimSpace(ts) |
| 439 | + |
| 440 | + n, err := strconv.ParseUint(s, 10, 64) |
| 441 | + |
| 442 | + if err != nil { |
| 443 | + return 0, err |
| 444 | + } |
| 445 | + |
| 446 | + // convert unit to bytes |
| 447 | + for j := 4 - i; j > 0; j-- { |
| 448 | + n = n * 1024 |
| 449 | + } |
| 450 | + |
| 451 | + return n, nil |
| 452 | + } |
| 453 | + } |
| 454 | + |
| 455 | + return 0, errors.New("invalid unit") |
| 456 | +} |
| 457 | + |
372 | 458 | // ReorderSpec defines details of packet reorder.
|
373 | 459 | type ReorderSpec struct {
|
374 | 460 | Reorder string `json:"reorder"`
|
|
0 commit comments