blob: 9249198c96dd1355b568a196fe97a10358e73f95 [file] [log] [blame]
khenaidoo6e55d9e2019-12-12 18:26:26 -05001/*
Kent Hagerman45a13e42020-04-13 12:23:50 -04002 * Copyright 2019-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
khenaidoo6e55d9e2019-12-12 18:26:26 -050015 */
Kent Hagerman45a13e42020-04-13 12:23:50 -040016
Kent Hagerman2b216042020-04-03 18:28:56 -040017package device
khenaidoo6e55d9e2019-12-12 18:26:26 -050018
19import (
20 "context"
Kent Hagermanf6db9f12020-07-22 17:16:19 -040021 "fmt"
Mahir Gunyel03de0d32020-06-03 01:36:59 -070022 "math/rand"
23 "sort"
Neha Sharmad1387da2020-05-07 20:07:28 +000024 "strconv"
Mahir Gunyel03de0d32020-06-03 01:36:59 -070025 "strings"
26 "sync"
27 "testing"
28 "time"
29
khenaidoo6e55d9e2019-12-12 18:26:26 -050030 "github.com/gogo/protobuf/proto"
Kent Hagerman2b216042020-04-03 18:28:56 -040031 "github.com/opencord/voltha-go/db/model"
khenaidoo6e55d9e2019-12-12 18:26:26 -050032 "github.com/opencord/voltha-go/rw_core/config"
Kent Hagerman2b216042020-04-03 18:28:56 -040033 "github.com/opencord/voltha-go/rw_core/core/adapter"
Mahir Gunyel03de0d32020-06-03 01:36:59 -070034 cm "github.com/opencord/voltha-go/rw_core/mocks"
35 tst "github.com/opencord/voltha-go/rw_core/test"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080036 com "github.com/opencord/voltha-lib-go/v3/pkg/adapters/common"
Kent Hagerman2b216042020-04-03 18:28:56 -040037 "github.com/opencord/voltha-lib-go/v3/pkg/db"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080038 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
Scott Baker504b4802020-04-17 10:12:20 -070039 "github.com/opencord/voltha-lib-go/v3/pkg/log"
Matteo Scandolod525ae32020-04-02 17:27:29 -070040 mock_etcd "github.com/opencord/voltha-lib-go/v3/pkg/mocks/etcd"
41 mock_kafka "github.com/opencord/voltha-lib-go/v3/pkg/mocks/kafka"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080042 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
43 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoo6e55d9e2019-12-12 18:26:26 -050044 "github.com/phayes/freeport"
45 "github.com/stretchr/testify/assert"
khenaidoo6e55d9e2019-12-12 18:26:26 -050046)
47
48type DATest struct {
Kent Hagerman2b216042020-04-03 18:28:56 -040049 etcdServer *mock_etcd.EtcdServer
50 deviceMgr *Manager
51 logicalDeviceMgr *LogicalManager
Mahir Gunyel03de0d32020-06-03 01:36:59 -070052 adapterMgr *adapter.Manager
Kent Hagerman2b216042020-04-03 18:28:56 -040053 kmp kafka.InterContainerProxy
54 kClient kafka.Client
55 kvClientPort int
Mahir Gunyel03de0d32020-06-03 01:36:59 -070056 oltAdapter *cm.OLTAdapter
57 onuAdapter *cm.ONUAdapter
Kent Hagerman2b216042020-04-03 18:28:56 -040058 oltAdapterName string
59 onuAdapterName string
60 coreInstanceID string
61 defaultTimeout time.Duration
62 maxTimeout time.Duration
63 device *voltha.Device
Kent Hagerman2a07b862020-06-19 15:23:07 -040064 devicePorts map[uint32]*voltha.Port
Kent Hagerman2b216042020-04-03 18:28:56 -040065 done chan int
khenaidoo6e55d9e2019-12-12 18:26:26 -050066}
67
Rohan Agrawal31f21802020-06-12 05:38:46 +000068func newDATest(ctx context.Context) *DATest {
khenaidoo6e55d9e2019-12-12 18:26:26 -050069 test := &DATest{}
70 // Start the embedded etcd server
71 var err error
Rohan Agrawal31f21802020-06-12 05:38:46 +000072 test.etcdServer, test.kvClientPort, err = tst.StartEmbeddedEtcdServer(ctx, "voltha.rwcore.da.test", "voltha.rwcore.da.etcd", "error")
khenaidoo6e55d9e2019-12-12 18:26:26 -050073 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +000074 logger.Fatal(ctx, err)
khenaidoo6e55d9e2019-12-12 18:26:26 -050075 }
76 // Create the kafka client
Matteo Scandolod525ae32020-04-02 17:27:29 -070077 test.kClient = mock_kafka.NewKafkaClient()
khenaidoo6e55d9e2019-12-12 18:26:26 -050078 test.oltAdapterName = "olt_adapter_mock"
79 test.onuAdapterName = "onu_adapter_mock"
80 test.coreInstanceID = "rw-da-test"
81 test.defaultTimeout = 5 * time.Second
82 test.maxTimeout = 20 * time.Second
83 test.done = make(chan int)
84 parentID := com.GetRandomString(10)
85 test.device = &voltha.Device{
86 Type: "onu_adapter_mock",
87 ParentId: parentID,
88 ParentPortNo: 1,
89 VendorId: "onu_adapter_mock",
90 Adapter: "onu_adapter_mock",
91 Vlan: 100,
92 Address: nil,
93 ProxyAddress: &voltha.Device_ProxyAddress{
94 DeviceId: parentID,
95 DeviceType: "olt_adapter_mock",
96 ChannelId: 100,
97 ChannelGroupId: 0,
98 ChannelTermination: "",
99 OnuId: 2,
100 },
101 AdminState: voltha.AdminState_PREPROVISIONED,
102 OperStatus: voltha.OperStatus_UNKNOWN,
103 Reason: "All good",
104 ConnectStatus: voltha.ConnectStatus_UNKNOWN,
105 Custom: nil,
Kent Hagerman2a07b862020-06-19 15:23:07 -0400106 }
107 test.devicePorts = map[uint32]*voltha.Port{
108 1: {PortNo: 1, Label: "pon-1", Type: voltha.Port_PON_ONU, AdminState: voltha.AdminState_ENABLED,
109 OperStatus: voltha.OperStatus_ACTIVE, Peers: []*voltha.Port_PeerPort{{DeviceId: parentID, PortNo: 1}}},
110 100: {PortNo: 100, Label: "uni-100", Type: voltha.Port_ETHERNET_UNI, AdminState: voltha.AdminState_ENABLED,
111 OperStatus: voltha.OperStatus_ACTIVE},
khenaidoo6e55d9e2019-12-12 18:26:26 -0500112 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500113 return test
114}
115
Rohan Agrawal31f21802020-06-12 05:38:46 +0000116func (dat *DATest) startCore(ctx context.Context) {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500117 cfg := config.NewRWCoreFlags()
serkant.uluderya8ff291d2020-05-20 00:58:00 -0700118 cfg.CoreTopic = "rw_core"
khenaidoo442e7c72020-03-10 16:13:48 -0400119 cfg.DefaultRequestTimeout = dat.defaultTimeout
Neha Sharmad1387da2020-05-07 20:07:28 +0000120 cfg.KVStoreAddress = "127.0.0.1" + ":" + strconv.Itoa(dat.kvClientPort)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500121 grpcPort, err := freeport.GetFreePort()
122 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000123 logger.Fatal(ctx, "Cannot get a freeport for grpc")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500124 }
Neha Sharmad1387da2020-05-07 20:07:28 +0000125 cfg.GrpcAddress = "127.0.0.1" + ":" + strconv.Itoa(grpcPort)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000126 client := tst.SetupKVClient(ctx, cfg, dat.coreInstanceID)
Kent Hagerman2b216042020-04-03 18:28:56 -0400127 backend := &db.Backend{
128 Client: client,
129 StoreType: cfg.KVStoreType,
Neha Sharmad1387da2020-05-07 20:07:28 +0000130 Address: cfg.KVStoreAddress,
Kent Hagerman2b216042020-04-03 18:28:56 -0400131 Timeout: cfg.KVStoreTimeout,
serkant.uluderya8ff291d2020-05-20 00:58:00 -0700132 LivenessChannelInterval: cfg.LiveProbeInterval / 2}
Kent Hagerman2b216042020-04-03 18:28:56 -0400133 dat.kmp = kafka.NewInterContainerProxy(
Neha Sharmad1387da2020-05-07 20:07:28 +0000134 kafka.InterContainerAddress(cfg.KafkaAdapterAddress),
Kent Hagerman2b216042020-04-03 18:28:56 -0400135 kafka.MsgClient(dat.kClient),
David Bainbridge9ae13132020-06-22 17:28:01 -0700136 kafka.DefaultTopic(&kafka.Topic{Name: cfg.CoreTopic}))
Kent Hagerman2b216042020-04-03 18:28:56 -0400137
138 endpointMgr := kafka.NewEndpointManager(backend)
Kent Hagermanf5a67352020-04-30 15:15:26 -0400139 proxy := model.NewDBPath(backend)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000140 dat.adapterMgr = adapter.NewAdapterManager(ctx, proxy, dat.coreInstanceID, dat.kClient)
Kent Hagerman2b216042020-04-03 18:28:56 -0400141
serkant.uluderya8ff291d2020-05-20 00:58:00 -0700142 dat.deviceMgr, dat.logicalDeviceMgr = NewManagers(proxy, dat.adapterMgr, dat.kmp, endpointMgr, cfg.CoreTopic, dat.coreInstanceID, cfg.DefaultCoreTimeout)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700143 dat.adapterMgr.Start(context.Background())
Rohan Agrawal31f21802020-06-12 05:38:46 +0000144 if err = dat.kmp.Start(ctx); err != nil {
145 logger.Fatal(ctx, "Cannot start InterContainerProxy")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530146 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700147
Rohan Agrawal31f21802020-06-12 05:38:46 +0000148 if err := dat.kmp.SubscribeWithDefaultRequestHandler(ctx, kafka.Topic{Name: cfg.CoreTopic}, kafka.OffsetNewest); err != nil {
149 logger.Fatalf(ctx, "Cannot add default request handler: %s", err)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700150 }
151
khenaidoo6e55d9e2019-12-12 18:26:26 -0500152}
153
Rohan Agrawal31f21802020-06-12 05:38:46 +0000154func (dat *DATest) stopAll(ctx context.Context) {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500155 if dat.kClient != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000156 dat.kClient.Stop(ctx)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500157 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400158 if dat.kmp != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000159 dat.kmp.Stop(ctx)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500160 }
161 if dat.etcdServer != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000162 tst.StopEmbeddedEtcdServer(ctx, dat.etcdServer)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500163 }
164}
165
Kent Hagerman2b216042020-04-03 18:28:56 -0400166func (dat *DATest) createDeviceAgent(t *testing.T) *Agent {
167 deviceMgr := dat.deviceMgr
khenaidoo6e55d9e2019-12-12 18:26:26 -0500168 clonedDevice := proto.Clone(dat.device).(*voltha.Device)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700169 deviceAgent := newAgent(deviceMgr.adapterProxy, clonedDevice, deviceMgr, deviceMgr.dbPath, deviceMgr.dProxy, deviceMgr.defaultTimeout)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500170 d, err := deviceAgent.start(context.TODO(), clonedDevice)
171 assert.Nil(t, err)
172 assert.NotNil(t, d)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400173 for _, port := range dat.devicePorts {
174 err := deviceAgent.addPort(context.TODO(), port)
175 assert.Nil(t, err)
176 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500177 deviceMgr.addDeviceAgentToMap(deviceAgent)
178 return deviceAgent
179}
180
Kent Hagerman2b216042020-04-03 18:28:56 -0400181func (dat *DATest) updateDeviceConcurrently(t *testing.T, da *Agent, globalWG *sync.WaitGroup) {
khenaidoo442e7c72020-03-10 16:13:48 -0400182 originalDevice, err := da.getDevice(context.Background())
Kent Hagerman2a07b862020-06-19 15:23:07 -0400183 originalDevicePorts := da.listDevicePorts()
khenaidoo442e7c72020-03-10 16:13:48 -0400184 assert.Nil(t, err)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500185 assert.NotNil(t, originalDevice)
186 var localWG sync.WaitGroup
187
188 // Update device routine
189 var (
190 root = false
191 vendor = "onu_adapter_mock"
192 model = "go-mock"
193 serialNumber = com.GetRandomSerialNumber()
194 macAddress = strings.ToUpper(com.GetRandomMacAddress())
195 vlan = rand.Uint32()
196 reason = "testing concurrent device update"
197 portToAdd = &voltha.Port{PortNo: 101, Label: "uni-101", Type: voltha.Port_ETHERNET_UNI, AdminState: voltha.AdminState_ENABLED,
198 OperStatus: voltha.OperStatus_ACTIVE}
199 )
200 localWG.Add(1)
201 go func() {
202 deviceToUpdate := proto.Clone(originalDevice).(*voltha.Device)
203 deviceToUpdate.Root = root
204 deviceToUpdate.Vendor = vendor
205 deviceToUpdate.Model = model
206 deviceToUpdate.SerialNumber = serialNumber
207 deviceToUpdate.MacAddress = macAddress
208 deviceToUpdate.Vlan = vlan
209 deviceToUpdate.Reason = reason
npujar467fe752020-01-16 20:17:45 +0530210 err := da.updateDeviceUsingAdapterData(context.Background(), deviceToUpdate)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500211 assert.Nil(t, err)
212 localWG.Done()
213 }()
214
215 // Update the device status routine
216 localWG.Add(1)
217 go func() {
npujar467fe752020-01-16 20:17:45 +0530218 err := da.updateDeviceStatus(context.Background(), voltha.OperStatus_ACTIVE, voltha.ConnectStatus_REACHABLE)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500219 assert.Nil(t, err)
220 localWG.Done()
221 }()
222
223 // Add a port routine
224 localWG.Add(1)
225 go func() {
npujar467fe752020-01-16 20:17:45 +0530226 err := da.addPort(context.Background(), portToAdd)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500227 assert.Nil(t, err)
228 localWG.Done()
229 }()
230
231 // wait for go routines to be done
232 localWG.Wait()
233
234 expectedChange := proto.Clone(originalDevice).(*voltha.Device)
235 expectedChange.OperStatus = voltha.OperStatus_ACTIVE
236 expectedChange.ConnectStatus = voltha.ConnectStatus_REACHABLE
khenaidoo6e55d9e2019-12-12 18:26:26 -0500237 expectedChange.Root = root
238 expectedChange.Vendor = vendor
239 expectedChange.Model = model
240 expectedChange.SerialNumber = serialNumber
241 expectedChange.MacAddress = macAddress
242 expectedChange.Vlan = vlan
243 expectedChange.Reason = reason
244
khenaidoo442e7c72020-03-10 16:13:48 -0400245 updatedDevice, _ := da.getDevice(context.Background())
Kent Hagerman2a07b862020-06-19 15:23:07 -0400246 updatedDevicePorts := da.listDevicePorts()
khenaidoo6e55d9e2019-12-12 18:26:26 -0500247 assert.NotNil(t, updatedDevice)
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400248 fmt.Printf("1 %+v\n", expectedChange)
249 fmt.Printf("2 %+v\n", updatedDevice)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500250 assert.True(t, proto.Equal(expectedChange, updatedDevice))
Kent Hagerman2a07b862020-06-19 15:23:07 -0400251 assert.Equal(t, len(originalDevicePorts)+1, len(updatedDevicePorts))
252 assert.True(t, proto.Equal(updatedDevicePorts[portToAdd.PortNo], portToAdd))
khenaidoo6e55d9e2019-12-12 18:26:26 -0500253
254 globalWG.Done()
255}
256
257func TestConcurrentDevices(t *testing.T) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000258 ctx := context.Background()
khenaidoo442e7c72020-03-10 16:13:48 -0400259 for i := 0; i < 2; i++ {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000260 da := newDATest(ctx)
khenaidoo442e7c72020-03-10 16:13:48 -0400261 assert.NotNil(t, da)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000262 defer da.stopAll(ctx)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700263 log.SetPackageLogLevel("github.com/opencord/voltha-go/rw_core/core", log.DebugLevel)
khenaidoo442e7c72020-03-10 16:13:48 -0400264 // Start the Core
Rohan Agrawal31f21802020-06-12 05:38:46 +0000265 da.startCore(ctx)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500266
khenaidoo442e7c72020-03-10 16:13:48 -0400267 var wg sync.WaitGroup
268 numConCurrentDeviceAgents := 20
269 for i := 0; i < numConCurrentDeviceAgents; i++ {
270 wg.Add(1)
271 a := da.createDeviceAgent(t)
272 go da.updateDeviceConcurrently(t, a, &wg)
273 }
274
275 wg.Wait()
khenaidoo6e55d9e2019-12-12 18:26:26 -0500276 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500277}
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700278func TestFlowUpdates(t *testing.T) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000279 ctx := context.Background()
280 da := newDATest(ctx)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700281 assert.NotNil(t, da)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000282 defer da.stopAll(ctx)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700283
284 log.SetPackageLogLevel("github.com/opencord/voltha-go/rw_core/core", log.DebugLevel)
285 // Start the Core
Rohan Agrawal31f21802020-06-12 05:38:46 +0000286 da.startCore(ctx)
287 da.oltAdapter, da.onuAdapter = tst.CreateAndregisterAdapters(ctx, t, da.kClient, da.coreInstanceID, da.oltAdapterName, da.onuAdapterName, da.adapterMgr)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700288
289 a := da.createDeviceAgent(t)
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400290 err1 := a.requestQueue.WaitForGreenLight(ctx)
291 assert.Nil(t, err1)
292 cloned := a.cloneDeviceWithoutLock()
293 cloned.AdminState, cloned.ConnectStatus, cloned.OperStatus = voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE
294 err2 := a.updateDeviceAndReleaseLock(ctx, cloned)
295 assert.Nil(t, err2)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700296 da.testFlowAddDeletes(t, a)
297}
298
299func TestGroupUpdates(t *testing.T) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000300 ctx := context.Background()
301 da := newDATest(ctx)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700302 assert.NotNil(t, da)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000303 defer da.stopAll(ctx)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700304
305 // Start the Core
Rohan Agrawal31f21802020-06-12 05:38:46 +0000306 da.startCore(ctx)
307 da.oltAdapter, da.onuAdapter = tst.CreateAndregisterAdapters(ctx, t, da.kClient, da.coreInstanceID, da.oltAdapterName, da.onuAdapterName, da.adapterMgr)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700308 a := da.createDeviceAgent(t)
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400309 err1 := a.requestQueue.WaitForGreenLight(ctx)
310 assert.Nil(t, err1)
311 cloned := a.cloneDeviceWithoutLock()
312 cloned.AdminState, cloned.ConnectStatus, cloned.OperStatus = voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE
313 err2 := a.updateDeviceAndReleaseLock(ctx, cloned)
314 assert.Nil(t, err2)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700315 da.testGroupAddDeletes(t, a)
316}
khenaidoob2121e52019-12-16 17:17:22 -0500317
318func isFlowSliceEqual(a, b []*ofp.OfpFlowStats) bool {
319 if len(a) != len(b) {
320 return false
321 }
322 sort.Slice(a, func(i, j int) bool {
323 return a[i].Id < a[j].Id
324 })
325 sort.Slice(b, func(i, j int) bool {
326 return b[i].Id < b[j].Id
327 })
328 for idx := range a {
329 if !proto.Equal(a[idx], b[idx]) {
330 return false
331 }
332 }
333 return true
334}
335
336func isGroupSliceEqual(a, b []*ofp.OfpGroupEntry) bool {
337 if len(a) != len(b) {
338 return false
339 }
340 sort.Slice(a, func(i, j int) bool {
341 return a[i].Desc.GroupId < a[j].Desc.GroupId
342 })
343 sort.Slice(b, func(i, j int) bool {
344 return b[i].Desc.GroupId < b[j].Desc.GroupId
345 })
346 for idx := range a {
347 if !proto.Equal(a[idx], b[idx]) {
348 return false
349 }
350 }
351 return true
352}
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700353func changeToFlowList(flowList map[uint64]*ofp.OfpFlowStats) []*ofp.OfpFlowStats {
354 flows := make([]*ofp.OfpFlowStats, 0)
355 for _, flow := range flowList {
356 flows = append(flows, flow)
357 }
358 return flows
khenaidoob2121e52019-12-16 17:17:22 -0500359}
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700360func changeToGroupList(groupList map[uint32]*ofp.OfpGroupEntry) []*ofp.OfpGroupEntry {
361 groups := make([]*ofp.OfpGroupEntry, 0)
362 for _, group := range groupList {
363 groups = append(groups, group)
364 }
365 return groups
366}
367func (dat *DATest) testFlowAddDeletes(t *testing.T, da *Agent) {
368 //Add new Flows on empty list
khenaidoob2121e52019-12-16 17:17:22 -0500369 newFlows := []*ofp.OfpFlowStats{
370 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
371 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
372 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
373 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700374 err := da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
375 assert.Nil(t, err)
376 daFlows := changeToFlowList(da.listDeviceFlows())
377 assert.True(t, isFlowSliceEqual(newFlows, daFlows))
khenaidoob2121e52019-12-16 17:17:22 -0500378
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700379 //Add new Flows on existing ones
380 newFlows = []*ofp.OfpFlowStats{
381 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500382 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270000, PacketCount: 0},
383 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700384
385 expectedFlows := []*ofp.OfpFlowStats{
386 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
387 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
388 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
389 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
390 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270000, PacketCount: 0},
391 }
392
393 err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
394 assert.Nil(t, err)
395 daFlows = changeToFlowList(da.listDeviceFlows())
396 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
397
398 //Add existing Flows again with a new flow
399 newFlows = []*ofp.OfpFlowStats{
400 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
401 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
402 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
403 }
404
405 expectedFlows = []*ofp.OfpFlowStats{
406 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
407 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
408 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
409 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
410 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
411 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
412 }
413
414 err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
415 assert.Nil(t, err)
416 daFlows = changeToFlowList(da.listDeviceFlows())
417 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
418
419 //Add already existing flows again
420 newFlows = []*ofp.OfpFlowStats{
421 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
422 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
423 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
424 }
425
426 expectedFlows = []*ofp.OfpFlowStats{
427 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
428 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
429 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
430 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
431 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
432 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
433 }
434
435 err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
436 assert.Nil(t, err)
437 daFlows = changeToFlowList(da.listDeviceFlows())
438 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
439
440 //Delete flows
441 flowsToDelete := []*ofp.OfpFlowStats{
442 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
443 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
444 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
445 }
446
447 expectedFlows = []*ofp.OfpFlowStats{
khenaidoob2121e52019-12-16 17:17:22 -0500448 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
449 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
450 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
451 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700452
453 err = da.deleteFlowsAndGroups(context.Background(), flowsToDelete, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
454 assert.Nil(t, err)
455 daFlows = changeToFlowList(da.listDeviceFlows())
456 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
457 //Delete flows with an unexisting one
458 flowsToDelete = []*ofp.OfpFlowStats{
khenaidoob2121e52019-12-16 17:17:22 -0500459 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700460 {Id: 129, TableId: 1290, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1290000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500461 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700462
463 expectedFlows = []*ofp.OfpFlowStats{
464 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500465 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500466 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700467
468 err = da.deleteFlowsAndGroups(context.Background(), flowsToDelete, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
469 assert.Nil(t, err)
470 daFlows = changeToFlowList(da.listDeviceFlows())
471 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
khenaidoob2121e52019-12-16 17:17:22 -0500472}
473
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700474func (dat *DATest) testGroupAddDeletes(t *testing.T, da *Agent) {
475 //Add new Groups on empty list
khenaidoob2121e52019-12-16 17:17:22 -0500476 newGroups := []*ofp.OfpGroupEntry{
477 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
478 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
479 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700480 err := da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
481 assert.Nil(t, err)
482 daGroups := changeToGroupList(da.listDeviceGroups())
483 assert.True(t, isGroupSliceEqual(newGroups, daGroups))
khenaidoob2121e52019-12-16 17:17:22 -0500484
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700485 //Add new Groups on existing ones
486 newGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500487 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
488 {Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, Buckets: nil}},
489 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700490 expectedGroups := []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500491 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
492 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
493 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
494 {Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, Buckets: nil}},
495 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700496 err = da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
497 assert.Nil(t, err)
498 daGroups = changeToGroupList(da.listDeviceGroups())
499 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
khenaidoob2121e52019-12-16 17:17:22 -0500500
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700501 //Add new Groups on existing ones
502 newGroups = []*ofp.OfpGroupEntry{
503 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
504 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
505 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500506 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700507 expectedGroups = []*ofp.OfpGroupEntry{
508 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500509 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
510 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700511 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
512 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500513 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700514 err = da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
515 assert.Nil(t, err)
516 daGroups = changeToGroupList(da.listDeviceGroups())
517 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
518
519 //Modify Group
520 updtGroups := []*ofp.OfpGroupEntry{
521 {Desc: &ofp.OfpGroupDesc{Type: 33, GroupId: 30, Buckets: nil}},
522 }
523 expectedGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500524 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500525 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700526 {Desc: &ofp.OfpGroupDesc{Type: 33, GroupId: 30, Buckets: nil}},
527 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
528 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500529 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700530 err = da.updateFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, updtGroups, &voltha.FlowMetadata{})
531 assert.Nil(t, err)
532 daGroups = changeToGroupList(da.listDeviceGroups())
533 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
534
535 //Delete Group
536 delGroups := []*ofp.OfpGroupEntry{
537 {Desc: &ofp.OfpGroupDesc{Type: 33, GroupId: 30, Buckets: nil}},
538 }
539 expectedGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500540 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700541 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
542 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
543 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
544 }
545 err = da.deleteFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, delGroups, &voltha.FlowMetadata{})
546 assert.Nil(t, err)
547 daGroups = changeToGroupList(da.listDeviceGroups())
548 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
549
550 //Delete Group
551 delGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500552 {Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, Buckets: nil}},
553 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700554 expectedGroups = []*ofp.OfpGroupEntry{
555 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
556 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
557 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
558 }
559 err = da.deleteFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, delGroups, &voltha.FlowMetadata{})
560 assert.Nil(t, err)
561 daGroups = changeToGroupList(da.listDeviceGroups())
562 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
khenaidoob2121e52019-12-16 17:17:22 -0500563}