blob: 29d8062bc9b9dd358081a76e477a54d8fa288c20 [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"
Mahir Gunyel03de0d32020-06-03 01:36:59 -070021 "math/rand"
22 "sort"
23 "strings"
24 "sync"
25 "testing"
26 "time"
27
khenaidoo6e55d9e2019-12-12 18:26:26 -050028 "github.com/gogo/protobuf/proto"
Kent Hagerman2b216042020-04-03 18:28:56 -040029 "github.com/opencord/voltha-go/db/model"
khenaidoo6e55d9e2019-12-12 18:26:26 -050030 "github.com/opencord/voltha-go/rw_core/config"
Kent Hagerman2b216042020-04-03 18:28:56 -040031 "github.com/opencord/voltha-go/rw_core/core/adapter"
Mahir Gunyel03de0d32020-06-03 01:36:59 -070032 cm "github.com/opencord/voltha-go/rw_core/mocks"
33 tst "github.com/opencord/voltha-go/rw_core/test"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080034 com "github.com/opencord/voltha-lib-go/v3/pkg/adapters/common"
Kent Hagerman2b216042020-04-03 18:28:56 -040035 "github.com/opencord/voltha-lib-go/v3/pkg/db"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080036 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
Scott Baker504b4802020-04-17 10:12:20 -070037 "github.com/opencord/voltha-lib-go/v3/pkg/log"
Matteo Scandolod525ae32020-04-02 17:27:29 -070038 mock_etcd "github.com/opencord/voltha-lib-go/v3/pkg/mocks/etcd"
39 mock_kafka "github.com/opencord/voltha-lib-go/v3/pkg/mocks/kafka"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080040 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
41 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoo6e55d9e2019-12-12 18:26:26 -050042 "github.com/phayes/freeport"
43 "github.com/stretchr/testify/assert"
khenaidoo6e55d9e2019-12-12 18:26:26 -050044)
45
46type DATest struct {
Kent Hagerman2b216042020-04-03 18:28:56 -040047 etcdServer *mock_etcd.EtcdServer
48 deviceMgr *Manager
49 logicalDeviceMgr *LogicalManager
Mahir Gunyel03de0d32020-06-03 01:36:59 -070050 adapterMgr *adapter.Manager
Kent Hagerman2b216042020-04-03 18:28:56 -040051 kmp kafka.InterContainerProxy
52 kClient kafka.Client
53 kvClientPort int
Mahir Gunyel03de0d32020-06-03 01:36:59 -070054 oltAdapter *cm.OLTAdapter
55 onuAdapter *cm.ONUAdapter
Kent Hagerman2b216042020-04-03 18:28:56 -040056 oltAdapterName string
57 onuAdapterName string
58 coreInstanceID string
59 defaultTimeout time.Duration
60 maxTimeout time.Duration
61 device *voltha.Device
62 done chan int
khenaidoo6e55d9e2019-12-12 18:26:26 -050063}
64
65func newDATest() *DATest {
66 test := &DATest{}
67 // Start the embedded etcd server
68 var err error
Mahir Gunyel03de0d32020-06-03 01:36:59 -070069 test.etcdServer, test.kvClientPort, err = tst.StartEmbeddedEtcdServer("voltha.rwcore.da.test", "voltha.rwcore.da.etcd", "error")
khenaidoo6e55d9e2019-12-12 18:26:26 -050070 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +000071 logger.Fatal(err)
khenaidoo6e55d9e2019-12-12 18:26:26 -050072 }
73 // Create the kafka client
Matteo Scandolod525ae32020-04-02 17:27:29 -070074 test.kClient = mock_kafka.NewKafkaClient()
khenaidoo6e55d9e2019-12-12 18:26:26 -050075 test.oltAdapterName = "olt_adapter_mock"
76 test.onuAdapterName = "onu_adapter_mock"
77 test.coreInstanceID = "rw-da-test"
78 test.defaultTimeout = 5 * time.Second
79 test.maxTimeout = 20 * time.Second
80 test.done = make(chan int)
81 parentID := com.GetRandomString(10)
82 test.device = &voltha.Device{
83 Type: "onu_adapter_mock",
84 ParentId: parentID,
85 ParentPortNo: 1,
86 VendorId: "onu_adapter_mock",
87 Adapter: "onu_adapter_mock",
88 Vlan: 100,
89 Address: nil,
90 ProxyAddress: &voltha.Device_ProxyAddress{
91 DeviceId: parentID,
92 DeviceType: "olt_adapter_mock",
93 ChannelId: 100,
94 ChannelGroupId: 0,
95 ChannelTermination: "",
96 OnuId: 2,
97 },
98 AdminState: voltha.AdminState_PREPROVISIONED,
99 OperStatus: voltha.OperStatus_UNKNOWN,
100 Reason: "All good",
101 ConnectStatus: voltha.ConnectStatus_UNKNOWN,
102 Custom: nil,
103 Ports: []*voltha.Port{
104 {PortNo: 1, Label: "pon-1", Type: voltha.Port_PON_ONU, AdminState: voltha.AdminState_ENABLED,
105 OperStatus: voltha.OperStatus_ACTIVE, Peers: []*voltha.Port_PeerPort{{DeviceId: parentID, PortNo: 1}}},
106 {PortNo: 100, Label: "uni-100", Type: voltha.Port_ETHERNET_UNI, AdminState: voltha.AdminState_ENABLED,
107 OperStatus: voltha.OperStatus_ACTIVE},
108 },
109 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500110 return test
111}
112
113func (dat *DATest) startCore(inCompeteMode bool) {
114 cfg := config.NewRWCoreFlags()
115 cfg.CorePairTopic = "rw_core"
khenaidoo442e7c72020-03-10 16:13:48 -0400116 cfg.DefaultRequestTimeout = dat.defaultTimeout
khenaidoo6e55d9e2019-12-12 18:26:26 -0500117 cfg.KVStorePort = dat.kvClientPort
118 cfg.InCompetingMode = inCompeteMode
119 grpcPort, err := freeport.GetFreePort()
120 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000121 logger.Fatal("Cannot get a freeport for grpc")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500122 }
123 cfg.GrpcPort = grpcPort
124 cfg.GrpcHost = "127.0.0.1"
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700125 client := tst.SetupKVClient(cfg, dat.coreInstanceID)
Kent Hagerman2b216042020-04-03 18:28:56 -0400126 backend := &db.Backend{
127 Client: client,
128 StoreType: cfg.KVStoreType,
129 Host: cfg.KVStoreHost,
130 Port: cfg.KVStorePort,
131 Timeout: cfg.KVStoreTimeout,
132 LivenessChannelInterval: cfg.LiveProbeInterval / 2,
133 PathPrefix: cfg.KVStoreDataPrefix}
134 dat.kmp = kafka.NewInterContainerProxy(
135 kafka.InterContainerHost(cfg.KafkaAdapterHost),
136 kafka.InterContainerPort(cfg.KafkaAdapterPort),
137 kafka.MsgClient(dat.kClient),
138 kafka.DefaultTopic(&kafka.Topic{Name: cfg.CoreTopic}),
139 kafka.DeviceDiscoveryTopic(&kafka.Topic{Name: cfg.AffinityRouterTopic}))
140
141 endpointMgr := kafka.NewEndpointManager(backend)
Kent Hagermanf5a67352020-04-30 15:15:26 -0400142 proxy := model.NewDBPath(backend)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700143 dat.adapterMgr = adapter.NewAdapterManager(proxy, dat.coreInstanceID, dat.kClient)
Kent Hagerman2b216042020-04-03 18:28:56 -0400144
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700145 dat.deviceMgr, dat.logicalDeviceMgr = NewManagers(proxy, dat.adapterMgr, dat.kmp, endpointMgr, cfg.CorePairTopic, dat.coreInstanceID, cfg.DefaultCoreTimeout)
146 dat.adapterMgr.Start(context.Background())
Kent Hagerman2b216042020-04-03 18:28:56 -0400147 if err = dat.kmp.Start(); err != nil {
148 logger.Fatal("Cannot start InterContainerProxy")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530149 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700150
151 if err := dat.kmp.SubscribeWithDefaultRequestHandler(kafka.Topic{Name: cfg.CorePairTopic}, kafka.OffsetNewest); err != nil {
152 logger.Fatalf("Cannot add default request handler: %s", err)
153 }
154
khenaidoo6e55d9e2019-12-12 18:26:26 -0500155}
156
157func (dat *DATest) stopAll() {
158 if dat.kClient != nil {
159 dat.kClient.Stop()
160 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400161 if dat.kmp != nil {
162 dat.kmp.Stop()
khenaidoo6e55d9e2019-12-12 18:26:26 -0500163 }
164 if dat.etcdServer != nil {
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700165 tst.StopEmbeddedEtcdServer(dat.etcdServer)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500166 }
167}
168
Kent Hagerman2b216042020-04-03 18:28:56 -0400169func (dat *DATest) createDeviceAgent(t *testing.T) *Agent {
170 deviceMgr := dat.deviceMgr
khenaidoo6e55d9e2019-12-12 18:26:26 -0500171 clonedDevice := proto.Clone(dat.device).(*voltha.Device)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700172 deviceAgent := newAgent(deviceMgr.adapterProxy, clonedDevice, deviceMgr, deviceMgr.dbPath, deviceMgr.dProxy, deviceMgr.defaultTimeout)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500173 d, err := deviceAgent.start(context.TODO(), clonedDevice)
174 assert.Nil(t, err)
175 assert.NotNil(t, d)
176 deviceMgr.addDeviceAgentToMap(deviceAgent)
177 return deviceAgent
178}
179
Kent Hagerman2b216042020-04-03 18:28:56 -0400180func (dat *DATest) updateDeviceConcurrently(t *testing.T, da *Agent, globalWG *sync.WaitGroup) {
khenaidoo442e7c72020-03-10 16:13:48 -0400181 originalDevice, err := da.getDevice(context.Background())
182 assert.Nil(t, err)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500183 assert.NotNil(t, originalDevice)
184 var localWG sync.WaitGroup
185
186 // Update device routine
187 var (
188 root = false
189 vendor = "onu_adapter_mock"
190 model = "go-mock"
191 serialNumber = com.GetRandomSerialNumber()
192 macAddress = strings.ToUpper(com.GetRandomMacAddress())
193 vlan = rand.Uint32()
194 reason = "testing concurrent device update"
195 portToAdd = &voltha.Port{PortNo: 101, Label: "uni-101", Type: voltha.Port_ETHERNET_UNI, AdminState: voltha.AdminState_ENABLED,
196 OperStatus: voltha.OperStatus_ACTIVE}
197 )
198 localWG.Add(1)
199 go func() {
200 deviceToUpdate := proto.Clone(originalDevice).(*voltha.Device)
201 deviceToUpdate.Root = root
202 deviceToUpdate.Vendor = vendor
203 deviceToUpdate.Model = model
204 deviceToUpdate.SerialNumber = serialNumber
205 deviceToUpdate.MacAddress = macAddress
206 deviceToUpdate.Vlan = vlan
207 deviceToUpdate.Reason = reason
npujar467fe752020-01-16 20:17:45 +0530208 err := da.updateDeviceUsingAdapterData(context.Background(), deviceToUpdate)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500209 assert.Nil(t, err)
210 localWG.Done()
211 }()
212
213 // Update the device status routine
214 localWG.Add(1)
215 go func() {
npujar467fe752020-01-16 20:17:45 +0530216 err := da.updateDeviceStatus(context.Background(), voltha.OperStatus_ACTIVE, voltha.ConnectStatus_REACHABLE)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500217 assert.Nil(t, err)
218 localWG.Done()
219 }()
220
221 // Add a port routine
222 localWG.Add(1)
223 go func() {
npujar467fe752020-01-16 20:17:45 +0530224 err := da.addPort(context.Background(), portToAdd)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500225 assert.Nil(t, err)
226 localWG.Done()
227 }()
228
229 // wait for go routines to be done
230 localWG.Wait()
231
232 expectedChange := proto.Clone(originalDevice).(*voltha.Device)
233 expectedChange.OperStatus = voltha.OperStatus_ACTIVE
234 expectedChange.ConnectStatus = voltha.ConnectStatus_REACHABLE
235 expectedChange.Ports = append(expectedChange.Ports, portToAdd)
236 expectedChange.Root = root
237 expectedChange.Vendor = vendor
238 expectedChange.Model = model
239 expectedChange.SerialNumber = serialNumber
240 expectedChange.MacAddress = macAddress
241 expectedChange.Vlan = vlan
242 expectedChange.Reason = reason
243
khenaidoo442e7c72020-03-10 16:13:48 -0400244 updatedDevice, _ := da.getDevice(context.Background())
khenaidoo6e55d9e2019-12-12 18:26:26 -0500245 assert.NotNil(t, updatedDevice)
246 assert.True(t, proto.Equal(expectedChange, updatedDevice))
247
248 globalWG.Done()
249}
250
251func TestConcurrentDevices(t *testing.T) {
khenaidoo442e7c72020-03-10 16:13:48 -0400252 for i := 0; i < 2; i++ {
253 da := newDATest()
254 assert.NotNil(t, da)
255 defer da.stopAll()
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700256 log.SetPackageLogLevel("github.com/opencord/voltha-go/rw_core/core", log.DebugLevel)
khenaidoo442e7c72020-03-10 16:13:48 -0400257 // Start the Core
258 da.startCore(false)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500259
khenaidoo442e7c72020-03-10 16:13:48 -0400260 var wg sync.WaitGroup
261 numConCurrentDeviceAgents := 20
262 for i := 0; i < numConCurrentDeviceAgents; i++ {
263 wg.Add(1)
264 a := da.createDeviceAgent(t)
265 go da.updateDeviceConcurrently(t, a, &wg)
266 }
267
268 wg.Wait()
khenaidoo6e55d9e2019-12-12 18:26:26 -0500269 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500270}
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700271func TestFlowUpdates(t *testing.T) {
272 da := newDATest()
273 assert.NotNil(t, da)
274 defer da.stopAll()
275
276 log.SetPackageLogLevel("github.com/opencord/voltha-go/rw_core/core", log.DebugLevel)
277 // Start the Core
278 da.startCore(false)
279 da.oltAdapter, da.onuAdapter = tst.CreateAndregisterAdapters(t, da.kClient, da.coreInstanceID, da.oltAdapterName, da.onuAdapterName, da.adapterMgr)
280
281 a := da.createDeviceAgent(t)
282 cloned := a.getDeviceWithoutLock()
283 err := a.updateDeviceStateInStoreWithoutLock(context.Background(), cloned, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
284 assert.Nil(t, err)
285 da.testFlowAddDeletes(t, a)
286}
287
288func TestGroupUpdates(t *testing.T) {
289 da := newDATest()
290 assert.NotNil(t, da)
291 defer da.stopAll()
292
293 // Start the Core
294 da.startCore(false)
295 da.oltAdapter, da.onuAdapter = tst.CreateAndregisterAdapters(t, da.kClient, da.coreInstanceID, da.oltAdapterName, da.onuAdapterName, da.adapterMgr)
296 a := da.createDeviceAgent(t)
297 cloned := a.getDeviceWithoutLock()
298 err := a.updateDeviceStateInStoreWithoutLock(context.Background(), cloned, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
299 assert.Nil(t, err)
300 da.testGroupAddDeletes(t, a)
301}
khenaidoob2121e52019-12-16 17:17:22 -0500302
303func isFlowSliceEqual(a, b []*ofp.OfpFlowStats) bool {
304 if len(a) != len(b) {
305 return false
306 }
307 sort.Slice(a, func(i, j int) bool {
308 return a[i].Id < a[j].Id
309 })
310 sort.Slice(b, func(i, j int) bool {
311 return b[i].Id < b[j].Id
312 })
313 for idx := range a {
314 if !proto.Equal(a[idx], b[idx]) {
315 return false
316 }
317 }
318 return true
319}
320
321func isGroupSliceEqual(a, b []*ofp.OfpGroupEntry) bool {
322 if len(a) != len(b) {
323 return false
324 }
325 sort.Slice(a, func(i, j int) bool {
326 return a[i].Desc.GroupId < a[j].Desc.GroupId
327 })
328 sort.Slice(b, func(i, j int) bool {
329 return b[i].Desc.GroupId < b[j].Desc.GroupId
330 })
331 for idx := range a {
332 if !proto.Equal(a[idx], b[idx]) {
333 return false
334 }
335 }
336 return true
337}
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700338func changeToFlowList(flowList map[uint64]*ofp.OfpFlowStats) []*ofp.OfpFlowStats {
339 flows := make([]*ofp.OfpFlowStats, 0)
340 for _, flow := range flowList {
341 flows = append(flows, flow)
342 }
343 return flows
khenaidoob2121e52019-12-16 17:17:22 -0500344}
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700345func changeToGroupList(groupList map[uint32]*ofp.OfpGroupEntry) []*ofp.OfpGroupEntry {
346 groups := make([]*ofp.OfpGroupEntry, 0)
347 for _, group := range groupList {
348 groups = append(groups, group)
349 }
350 return groups
351}
352func (dat *DATest) testFlowAddDeletes(t *testing.T, da *Agent) {
353 //Add new Flows on empty list
khenaidoob2121e52019-12-16 17:17:22 -0500354 newFlows := []*ofp.OfpFlowStats{
355 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
356 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
357 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
358 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700359 err := da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
360 assert.Nil(t, err)
361 daFlows := changeToFlowList(da.listDeviceFlows())
362 assert.True(t, isFlowSliceEqual(newFlows, daFlows))
khenaidoob2121e52019-12-16 17:17:22 -0500363
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700364 //Add new Flows on existing ones
365 newFlows = []*ofp.OfpFlowStats{
366 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500367 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270000, PacketCount: 0},
368 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700369
370 expectedFlows := []*ofp.OfpFlowStats{
371 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
372 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
373 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
374 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
375 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270000, PacketCount: 0},
376 }
377
378 err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
379 assert.Nil(t, err)
380 daFlows = changeToFlowList(da.listDeviceFlows())
381 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
382
383 //Add existing Flows again with a new flow
384 newFlows = []*ofp.OfpFlowStats{
385 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
386 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
387 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
388 }
389
390 expectedFlows = []*ofp.OfpFlowStats{
391 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
392 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
393 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
394 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
395 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
396 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
397 }
398
399 err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
400 assert.Nil(t, err)
401 daFlows = changeToFlowList(da.listDeviceFlows())
402 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
403
404 //Add already existing flows again
405 newFlows = []*ofp.OfpFlowStats{
406 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
407 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
408 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
409 }
410
411 expectedFlows = []*ofp.OfpFlowStats{
412 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
413 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
414 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
415 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
416 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
417 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
418 }
419
420 err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
421 assert.Nil(t, err)
422 daFlows = changeToFlowList(da.listDeviceFlows())
423 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
424
425 //Delete flows
426 flowsToDelete := []*ofp.OfpFlowStats{
427 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
428 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
429 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
430 }
431
432 expectedFlows = []*ofp.OfpFlowStats{
khenaidoob2121e52019-12-16 17:17:22 -0500433 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
434 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
435 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
436 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700437
438 err = da.deleteFlowsAndGroups(context.Background(), flowsToDelete, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
439 assert.Nil(t, err)
440 daFlows = changeToFlowList(da.listDeviceFlows())
441 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
442 //Delete flows with an unexisting one
443 flowsToDelete = []*ofp.OfpFlowStats{
khenaidoob2121e52019-12-16 17:17:22 -0500444 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700445 {Id: 129, TableId: 1290, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1290000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500446 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700447
448 expectedFlows = []*ofp.OfpFlowStats{
449 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500450 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500451 }
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))
khenaidoob2121e52019-12-16 17:17:22 -0500457}
458
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700459func (dat *DATest) testGroupAddDeletes(t *testing.T, da *Agent) {
460 //Add new Groups on empty list
khenaidoob2121e52019-12-16 17:17:22 -0500461 newGroups := []*ofp.OfpGroupEntry{
462 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
463 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
464 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700465 err := da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
466 assert.Nil(t, err)
467 daGroups := changeToGroupList(da.listDeviceGroups())
468 assert.True(t, isGroupSliceEqual(newGroups, daGroups))
khenaidoob2121e52019-12-16 17:17:22 -0500469
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700470 //Add new Groups on existing ones
471 newGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500472 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
473 {Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, Buckets: nil}},
474 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700475 expectedGroups := []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500476 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
477 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
478 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
479 {Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, Buckets: nil}},
480 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700481 err = da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
482 assert.Nil(t, err)
483 daGroups = changeToGroupList(da.listDeviceGroups())
484 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
khenaidoob2121e52019-12-16 17:17:22 -0500485
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700486 //Add new Groups on existing ones
487 newGroups = []*ofp.OfpGroupEntry{
488 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
489 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
490 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500491 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700492 expectedGroups = []*ofp.OfpGroupEntry{
493 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500494 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
495 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700496 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
497 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500498 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700499 err = da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
500 assert.Nil(t, err)
501 daGroups = changeToGroupList(da.listDeviceGroups())
502 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
503
504 //Modify Group
505 updtGroups := []*ofp.OfpGroupEntry{
506 {Desc: &ofp.OfpGroupDesc{Type: 33, GroupId: 30, Buckets: nil}},
507 }
508 expectedGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500509 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500510 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700511 {Desc: &ofp.OfpGroupDesc{Type: 33, GroupId: 30, Buckets: nil}},
512 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
513 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500514 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700515 err = da.updateFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, updtGroups, &voltha.FlowMetadata{})
516 assert.Nil(t, err)
517 daGroups = changeToGroupList(da.listDeviceGroups())
518 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
519
520 //Delete Group
521 delGroups := []*ofp.OfpGroupEntry{
522 {Desc: &ofp.OfpGroupDesc{Type: 33, GroupId: 30, Buckets: nil}},
523 }
524 expectedGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500525 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700526 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
527 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
528 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
529 }
530 err = da.deleteFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, delGroups, &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{
khenaidoob2121e52019-12-16 17:17:22 -0500537 {Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, Buckets: nil}},
538 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700539 expectedGroups = []*ofp.OfpGroupEntry{
540 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
541 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
542 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
543 }
544 err = da.deleteFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, delGroups, &voltha.FlowMetadata{})
545 assert.Nil(t, err)
546 daGroups = changeToGroupList(da.listDeviceGroups())
547 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
khenaidoob2121e52019-12-16 17:17:22 -0500548}