1
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
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
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
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