...

Source file src/edge-infra.dev/pkg/sds/ien/k8s/controllers/nodeagent/plugins/networking/trafficshaping/trafficshaping_test.go

Documentation: edge-infra.dev/pkg/sds/ien/k8s/controllers/nodeagent/plugins/networking/trafficshaping

     1  //go:build linux
     2  
     3  package trafficshaping
     4  
     5  import (
     6  	"context"
     7  	_ "embed"
     8  	"os"
     9  	"strconv"
    10  	"testing"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/vishvananda/netns"
    14  	v1 "k8s.io/api/core/v1"
    15  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    16  	kruntime "k8s.io/apimachinery/pkg/runtime"
    17  	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
    18  	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
    19  	"sigs.k8s.io/controller-runtime/pkg/client"
    20  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    21  
    22  	"edge-infra.dev/pkg/lib/kernel/netlink/modules"
    23  	testnetns "edge-infra.dev/pkg/lib/kernel/netlink/netns"
    24  
    25  	v1ien "edge-infra.dev/pkg/sds/ien/k8s/apis/v1"
    26  
    27  	"edge-infra.dev/pkg/lib/uuid"
    28  	"edge-infra.dev/pkg/sds/ien/k8s/controllers/nodeagent/config"
    29  	"edge-infra.dev/test/f2"
    30  )
    31  
    32  var (
    33  	nodeIP  = "192.168.1.2/24"
    34  	nodeIP2 = "192.168.1.3/24"
    35  	gateway = "192.168.1.1"
    36  	dns     = "8.8.8.8"
    37  	mac     = "98:72:76:4a:87:0f"
    38  	mac2    = "95:64:af:0a:b1:dd"
    39  )
    40  
    41  var f f2.Framework
    42  
    43  func TestMain(m *testing.M) {
    44  	f = f2.New(context.Background(), f2.WithExtensions()).
    45  		Setup().
    46  		Teardown()
    47  	os.Exit(f.Run(m))
    48  }
    49  
    50  // nolint:dupl
    51  func TestTrafficShapingEnabled(t *testing.T) {
    52  	var tearDownFunction func()
    53  	var kclient client.Client
    54  	var cfg config.Config
    55  	var ienode *v1ien.IENode
    56  	var ns netns.NsHandle
    57  
    58  	if err := modules.RequiredKernelModulesLoaded(); err != nil {
    59  		t.Skip("missing required kernel modules for tc")
    60  	}
    61  
    62  	feature := f2.NewFeature("enable traffic shaping").
    63  		Setup("setup testing namespace", func(ctx f2.Context, t *testing.T) f2.Context {
    64  			// until we figure out how to test with kernel modules installed these tests will be skipped
    65  			ns, tearDownFunction = testnetns.NewTestingNetworkNamespace(t)
    66  			assert.NoError(t, testnetns.CreateDummyLink())
    67  
    68  			dev, err := testnetns.GetDummyLink()
    69  			assert.NoError(t, err)
    70  
    71  			ienode = staticIPCPNode()
    72  			ienode.Spec.Network[0].MacAddress = dev.Attrs().HardwareAddr.String()
    73  
    74  			kclient = fake.NewClientBuilder().WithScheme(createScheme()).WithObjects(createTopologyInfoConfigMap(true, "4mbit", "4mbit"), ienode).Build()
    75  			cfg = config.NewConfig(kclient, nil, nil, config.Flags{})
    76  			return ctx
    77  		}).
    78  		Test("check qdiscs, classes, and filters are created", func(ctx f2.Context, t *testing.T) f2.Context {
    79  			assert.NoError(t, netns.Set(ns))
    80  			_, err := Plugin{}.Reconcile(ctx, ienode, cfg)
    81  			assert.NoError(t, err)
    82  
    83  			return ctx
    84  		}).
    85  		Teardown("teardown testing namespace", func(ctx f2.Context, _ *testing.T) f2.Context {
    86  			tearDownFunction()
    87  			return ctx
    88  		}).Feature()
    89  
    90  	f.Test(t, feature)
    91  }
    92  
    93  // nolint:dupl
    94  func TestTrafficShapingEnabledWithPrimaryInterface(t *testing.T) {
    95  	var tearDownFunction func()
    96  	var kclient client.Client
    97  	var cfg config.Config
    98  	var ienode *v1ien.IENode
    99  	var ns netns.NsHandle
   100  
   101  	if err := modules.RequiredKernelModulesLoaded(); err != nil {
   102  		t.Skip("missing required kernel modules for tc")
   103  	}
   104  
   105  	feature := f2.NewFeature("enable traffic shaping").
   106  		Setup("setup testing namespace", func(ctx f2.Context, t *testing.T) f2.Context {
   107  			ns, tearDownFunction = testnetns.NewTestingNetworkNamespace(t)
   108  			assert.NoError(t, testnetns.CreateDummyLink())
   109  
   110  			dev, err := testnetns.GetDummyLink()
   111  			assert.NoError(t, err)
   112  
   113  			ienode = staticIPCPNodeWithPrimaryInterface()
   114  			ienode.Spec.Network[1].MacAddress = dev.Attrs().HardwareAddr.String()
   115  
   116  			kclient = fake.NewClientBuilder().WithScheme(createScheme()).WithObjects(createTopologyInfoConfigMap(true, "4mbit", "4mbit"), ienode).Build()
   117  			cfg = config.NewConfig(kclient, nil, nil, config.Flags{})
   118  
   119  			return ctx
   120  		}).
   121  		Test("check qdiscs, classes, and filters are created", func(ctx f2.Context, t *testing.T) f2.Context {
   122  			assert.NoError(t, netns.Set(ns))
   123  			_, err := Plugin{}.Reconcile(ctx, ienode, cfg)
   124  			assert.NoError(t, err)
   125  
   126  			return ctx
   127  		}).
   128  		Teardown("teardown testing namespace", func(ctx f2.Context, _ *testing.T) f2.Context {
   129  			tearDownFunction()
   130  			return ctx
   131  		}).Feature()
   132  
   133  	f.Test(t, feature)
   134  }
   135  
   136  func createScheme() *kruntime.Scheme {
   137  	scheme := kruntime.NewScheme()
   138  	utilruntime.Must(clientgoscheme.AddToScheme(scheme))
   139  	utilruntime.Must(v1.AddToScheme(scheme))
   140  	utilruntime.Must(v1ien.AddToScheme(scheme))
   141  	return scheme
   142  }
   143  
   144  func createTopologyInfoConfigMap(gatewayRateLimitingEnabled bool, upLinkRate, downLinkRate string) *v1.ConfigMap {
   145  	return &v1.ConfigMap{
   146  		ObjectMeta: metav1.ObjectMeta{
   147  			Name:      "topology-info",
   148  			Namespace: "kube-public",
   149  		},
   150  		Data: map[string]string{
   151  			"gateway_rate_limiting_enabled": strconv.FormatBool(gatewayRateLimitingEnabled),
   152  			"uplink_rate_limit":             upLinkRate,
   153  			"downlink_rate_limit":           downLinkRate,
   154  		},
   155  	}
   156  }
   157  
   158  func staticIPCPNode() *v1ien.IENode {
   159  	return &v1ien.IENode{
   160  		ObjectMeta: metav1.ObjectMeta{
   161  			Name: uuid.New().UUID,
   162  		},
   163  		Spec: v1ien.IENodeSpec{
   164  			Role: v1ien.ControlPlane,
   165  			Lane: "1",
   166  			NetworkServices: v1ien.NetworkServices{
   167  				DNSServers: []string{dns},
   168  			},
   169  			Network: []v1ien.Network{
   170  				{
   171  					Addresses: []string{nodeIP},
   172  					Gateway4:  gateway,
   173  					DHCP4:     false,
   174  				},
   175  			},
   176  		},
   177  	}
   178  }
   179  
   180  func staticIPCPNodeWithPrimaryInterface() *v1ien.IENode {
   181  	return &v1ien.IENode{
   182  		ObjectMeta: metav1.ObjectMeta{
   183  			Name: uuid.New().UUID,
   184  		},
   185  		Spec: v1ien.IENodeSpec{
   186  			Role: v1ien.ControlPlane,
   187  			Lane: "1",
   188  			NetworkServices: v1ien.NetworkServices{
   189  				DNSServers: []string{dns},
   190  			},
   191  			Network: []v1ien.Network{
   192  				{
   193  					Addresses:  []string{nodeIP},
   194  					Gateway4:   gateway,
   195  					DHCP4:      false,
   196  					MacAddress: mac,
   197  				},
   198  				{
   199  					Addresses:  []string{nodeIP2},
   200  					Gateway4:   gateway,
   201  					DHCP4:      false,
   202  					MacAddress: mac2,
   203  				},
   204  			},
   205  			PrimaryInterface: &v1ien.PrimaryInterface{
   206  				InterfaceID:  "341ba167-b8ea-43f2-8f76-a0b855a2f818",
   207  				MacAddresses: []string{mac2},
   208  			},
   209  		},
   210  	}
   211  }
   212  

View as plain text