Testground
GitHubGo SDKInfra
master
master
  • README
  • Table of contents
    • What is Testground?
      • Community
    • Concepts and architecture
      • Test plans and test cases
      • Daemon and client
      • Synchronization service
      • Networking
      • Sidecar
      • Builders
      • Runners
      • Runtime environment (runenv)
      • Client-Server communication
    • Getting started
    • Writing test plans
      • Quick start
      • Understanding the test plan manifest
      • Parameters and test cases
      • Keeping instances in sync
      • Communication between instances
      • Observability, assets and metrics
    • Managing test plans
    • Running test plans
    • Traffic shaping
    • Analyzing test run results
      • Capturing profiles
    • Debugging test plans
    • Docker Settings
    • Featured projects
  • Runner library
    • local:exec
    • local:docker
      • System overview
      • Runner flags
      • Troubleshooting
    • cluster:k8s
      • System overview
      • How to create a Kubernetes cluster for Testground
      • Monitoring and Observability
      • Understanding Testground performance on Kubernetes
      • Troubleshooting
  • Builder Library
    • docker:go
    • exec:go
    • docker:generic
Powered by GitBook
On this page
  • Imports
  • Pre-check and preparation
  • Network initialization
  • Configure traffic shaping
  • (Optional) Changing your IP address
  • Apply the configuration
  • Appendix: What the sidecar does
  1. Table of contents

Traffic shaping

PreviousRunning test plansNextAnalyzing test run results

Last updated 2 years ago

In Testground, a test instance can configure its own network (IP address, jitter, latency, bandwidth, etc.) using a network client. See the for more information.

Imports

For this example, you'll need the following packages:

import (
    "net"

    "github.com/testground/sdk-go/network"
    "github.com/testground/sdk-go/runtime"
    "github.com/testground/sdk-go/sync"
)

Pre-check and preparation

First, check to make sure the sidecar is available. At the moment, it's only available on docker-based runners. If it's not available, just skip any networking config code and return.

// runenv is the test instances run environment (runtime.RunEnv).
if !runenv.TestSidecar {
    return
}

// client is the *sync.Client
netclient := network.NewClient(client, runenv)

Network initialization

netclient.MustWaitNetworkInitialized(ctx)

If you don't want to customize the network (set IP addresses, latency, etc.), you can stop here.

Configure traffic shaping

Once the network is ready, you'll need to actually configure your network. To "shape" traffic, set the Default LinkShape. You can use this to set latency, bandwidth, jitter, etc.

config := network.Config{
    // Control the "default" network. At the moment, this is the only network.
    Network: "default",

    // Enable this network. Setting this to false will disconnect this test
    // instance from this network. You probably don't want to do that.
    Enable:  true,

    // Set the traffic shaping characteristics.
    Default: network.LinkShape{
        Latency:   100 * time.Millisecond,
        Bandwidth: 1 << 20, // 1Mib
    },

    // Set what state the sidecar should signal back to you when it's done.
    CallbackState: "network-configured",
}

?> This sets egress (outbound) properties on the link. These settings must be symmetric (applied on both sides of the connection) to work properly (unless asymmetric bandwidth/latency/etc. is desired).

?> Per-subnet traffic shaping is a desired but unimplemented feature. The sidecar will reject configs with per-subnet rules set in network.Config.Rules

(Optional) Changing your IP address

If you don't specify an IPv4 address when configuring your network, your test instance will keep the default assignment. However, if desired, a test instance can change its IP address at any time.

First, you'll need some kind of unique sequence number to ensure you don't pick conflicting IP addresses. If you don't already have some form of unique sequence number at this point in your tests, use the sync service to get one:

topic := sync.NewTopic("ip-allocation", "")
seq := sync.MustPublish(ctx, topic, "")

Once you have a sequence number, you can set your IP address from one of the available subnets:

// copy the test subnet.
config.IPv4 = &*runenv.TestSubnet
// Use the sequence number to fill in the last two octets.
//
// NOTE: Be careful not to modify the IP from `runenv.TestSubnet`.
// That could trigger undefined behavior.
ipC := byte((seq >> 8) + 1)
ipD := byte(seq)
config.IPv4.IP = append(config.IPv4.IP[0:2:2], ipC, ipD)

You cannot currently set an IPv6 address.

Apply the configuration

Applying the network configuration will post the configuration to the sync service, from where the appropriate instance of sidecar will consume it to apply the rules via Netlink. Once it is done, it will signal back on the CallbackState.

?> The network API will, by default, wait for runenv.TestInstanceCount instances to have signalled on the CallbackState. If you want to wait for a different number of instances, such as if only a subset of instances actually apply traffic shaping rules, you can set the CallbackTarget value in the configuration.

err := netclient.ConfigureNetwork(ctx, config)
if err != nil {
    runenv.Abort(err)
    return
}

Appendix: What the sidecar does

  1. The sidecar reads the network configuration from the sync service.

  2. The sidecar applies network configurations requested by test plan instances.

  3. The sidecar signals the configured CallbackState when done.

Wait for the sidecar to initialize the network for this test plan instance. See the section for more details.

network package of the Go SDK
Networking