blob: 93277ffb532fe2200e16454f9b46db7e3df5c834 [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"
Neha Sharmad1387da2020-05-07 20:07:28 +000023 "strconv"
Mahir Gunyel03de0d32020-06-03 01:36:59 -070024 "strings"
25 "sync"
26 "testing"
27 "time"
28
khenaidoo6e55d9e2019-12-12 18:26:26 -050029 "github.com/gogo/protobuf/proto"
Kent Hagerman2b216042020-04-03 18:28:56 -040030 "github.com/opencord/voltha-go/db/model"
khenaidoo6e55d9e2019-12-12 18:26:26 -050031 "github.com/opencord/voltha-go/rw_core/config"
Kent Hagerman2b216042020-04-03 18:28:56 -040032 "github.com/opencord/voltha-go/rw_core/core/adapter"
Mahir Gunyel03de0d32020-06-03 01:36:59 -070033 cm "github.com/opencord/voltha-go/rw_core/mocks"
34 tst "github.com/opencord/voltha-go/rw_core/test"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080035 com "github.com/opencord/voltha-lib-go/v3/pkg/adapters/common"
Kent Hagerman2b216042020-04-03 18:28:56 -040036 "github.com/opencord/voltha-lib-go/v3/pkg/db"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080037 "github.com/opencord/voltha-lib-go/v3/pkg/kafka"
Scott Baker504b4802020-04-17 10:12:20 -070038 "github.com/opencord/voltha-lib-go/v3/pkg/log"
Matteo Scandolod525ae32020-04-02 17:27:29 -070039 mock_etcd "github.com/opencord/voltha-lib-go/v3/pkg/mocks/etcd"
40 mock_kafka "github.com/opencord/voltha-lib-go/v3/pkg/mocks/kafka"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080041 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
42 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoo6e55d9e2019-12-12 18:26:26 -050043 "github.com/phayes/freeport"
44 "github.com/stretchr/testify/assert"
khenaidoo6e55d9e2019-12-12 18:26:26 -050045)
46
47type DATest struct {
Kent Hagerman2b216042020-04-03 18:28:56 -040048 etcdServer *mock_etcd.EtcdServer
49 deviceMgr *Manager
50 logicalDeviceMgr *LogicalManager
Mahir Gunyel03de0d32020-06-03 01:36:59 -070051 adapterMgr *adapter.Manager
Kent Hagerman2b216042020-04-03 18:28:56 -040052 kmp kafka.InterContainerProxy
53 kClient kafka.Client
54 kvClientPort int
Mahir Gunyel03de0d32020-06-03 01:36:59 -070055 oltAdapter *cm.OLTAdapter
56 onuAdapter *cm.ONUAdapter
Kent Hagerman2b216042020-04-03 18:28:56 -040057 oltAdapterName string
58 onuAdapterName string
59 coreInstanceID string
60 defaultTimeout time.Duration
61 maxTimeout time.Duration
62 device *voltha.Device
63 done chan int
khenaidoo6e55d9e2019-12-12 18:26:26 -050064}
65
66func newDATest() *DATest {
67 test := &DATest{}
68 // Start the embedded etcd server
69 var err error
Mahir Gunyel03de0d32020-06-03 01:36:59 -070070 test.etcdServer, test.kvClientPort, err = tst.StartEmbeddedEtcdServer("voltha.rwcore.da.test", "voltha.rwcore.da.etcd", "error")
khenaidoo6e55d9e2019-12-12 18:26:26 -050071 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +000072 logger.Fatal(err)
khenaidoo6e55d9e2019-12-12 18:26:26 -050073 }
74 // Create the kafka client
Matteo Scandolod525ae32020-04-02 17:27:29 -070075 test.kClient = mock_kafka.NewKafkaClient()
khenaidoo6e55d9e2019-12-12 18:26:26 -050076 test.oltAdapterName = "olt_adapter_mock"
77 test.onuAdapterName = "onu_adapter_mock"
78 test.coreInstanceID = "rw-da-test"
79 test.defaultTimeout = 5 * time.Second
80 test.maxTimeout = 20 * time.Second
81 test.done = make(chan int)
82 parentID := com.GetRandomString(10)
83 test.device = &voltha.Device{
84 Type: "onu_adapter_mock",
85 ParentId: parentID,
86 ParentPortNo: 1,
87 VendorId: "onu_adapter_mock",
88 Adapter: "onu_adapter_mock",
89 Vlan: 100,
90 Address: nil,
91 ProxyAddress: &voltha.Device_ProxyAddress{
92 DeviceId: parentID,
93 DeviceType: "olt_adapter_mock",
94 ChannelId: 100,
95 ChannelGroupId: 0,
96 ChannelTermination: "",
97 OnuId: 2,
98 },
99 AdminState: voltha.AdminState_PREPROVISIONED,
100 OperStatus: voltha.OperStatus_UNKNOWN,
101 Reason: "All good",
102 ConnectStatus: voltha.ConnectStatus_UNKNOWN,
103 Custom: nil,
104 Ports: []*voltha.Port{
105 {PortNo: 1, Label: "pon-1", Type: voltha.Port_PON_ONU, AdminState: voltha.AdminState_ENABLED,
106 OperStatus: voltha.OperStatus_ACTIVE, Peers: []*voltha.Port_PeerPort{{DeviceId: parentID, PortNo: 1}}},
107 {PortNo: 100, Label: "uni-100", Type: voltha.Port_ETHERNET_UNI, AdminState: voltha.AdminState_ENABLED,
108 OperStatus: voltha.OperStatus_ACTIVE},
109 },
110 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500111 return test
112}
113
114func (dat *DATest) startCore(inCompeteMode bool) {
115 cfg := config.NewRWCoreFlags()
serkant.uluderya8ff291d2020-05-20 00:58:00 -0700116 cfg.CoreTopic = "rw_core"
khenaidoo442e7c72020-03-10 16:13:48 -0400117 cfg.DefaultRequestTimeout = dat.defaultTimeout
Neha Sharmad1387da2020-05-07 20:07:28 +0000118 cfg.KVStoreAddress = "127.0.0.1" + ":" + strconv.Itoa(dat.kvClientPort)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500119 cfg.InCompetingMode = inCompeteMode
120 grpcPort, err := freeport.GetFreePort()
121 if err != nil {
Girish Kumarf56a4682020-03-20 20:07:46 +0000122 logger.Fatal("Cannot get a freeport for grpc")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500123 }
Neha Sharmad1387da2020-05-07 20:07:28 +0000124 cfg.GrpcAddress = "127.0.0.1" + ":" + strconv.Itoa(grpcPort)
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,
Neha Sharmad1387da2020-05-07 20:07:28 +0000129 Address: cfg.KVStoreAddress,
Kent Hagerman2b216042020-04-03 18:28:56 -0400130 Timeout: cfg.KVStoreTimeout,
serkant.uluderya8ff291d2020-05-20 00:58:00 -0700131 LivenessChannelInterval: cfg.LiveProbeInterval / 2}
Kent Hagerman2b216042020-04-03 18:28:56 -0400132 dat.kmp = kafka.NewInterContainerProxy(
Neha Sharmad1387da2020-05-07 20:07:28 +0000133 kafka.InterContainerAddress(cfg.KafkaAdapterAddress),
Kent Hagerman2b216042020-04-03 18:28:56 -0400134 kafka.MsgClient(dat.kClient),
135 kafka.DefaultTopic(&kafka.Topic{Name: cfg.CoreTopic}),
136 kafka.DeviceDiscoveryTopic(&kafka.Topic{Name: cfg.AffinityRouterTopic}))
137
138 endpointMgr := kafka.NewEndpointManager(backend)
Kent Hagermanf5a67352020-04-30 15:15:26 -0400139 proxy := model.NewDBPath(backend)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700140 dat.adapterMgr = adapter.NewAdapterManager(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())
Kent Hagerman2b216042020-04-03 18:28:56 -0400144 if err = dat.kmp.Start(); err != nil {
145 logger.Fatal("Cannot start InterContainerProxy")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530146 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700147
serkant.uluderya8ff291d2020-05-20 00:58:00 -0700148 if err := dat.kmp.SubscribeWithDefaultRequestHandler(kafka.Topic{Name: cfg.CoreTopic}, kafka.OffsetNewest); err != nil {
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700149 logger.Fatalf("Cannot add default request handler: %s", err)
150 }
151
khenaidoo6e55d9e2019-12-12 18:26:26 -0500152}
153
154func (dat *DATest) stopAll() {
155 if dat.kClient != nil {
156 dat.kClient.Stop()
157 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400158 if dat.kmp != nil {
159 dat.kmp.Stop()
khenaidoo6e55d9e2019-12-12 18:26:26 -0500160 }
161 if dat.etcdServer != nil {
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700162 tst.StopEmbeddedEtcdServer(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)
173 deviceMgr.addDeviceAgentToMap(deviceAgent)
174 return deviceAgent
175}
176
Kent Hagerman2b216042020-04-03 18:28:56 -0400177func (dat *DATest) updateDeviceConcurrently(t *testing.T, da *Agent, globalWG *sync.WaitGroup) {
khenaidoo442e7c72020-03-10 16:13:48 -0400178 originalDevice, err := da.getDevice(context.Background())
179 assert.Nil(t, err)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500180 assert.NotNil(t, originalDevice)
181 var localWG sync.WaitGroup
182
183 // Update device routine
184 var (
185 root = false
186 vendor = "onu_adapter_mock"
187 model = "go-mock"
188 serialNumber = com.GetRandomSerialNumber()
189 macAddress = strings.ToUpper(com.GetRandomMacAddress())
190 vlan = rand.Uint32()
191 reason = "testing concurrent device update"
192 portToAdd = &voltha.Port{PortNo: 101, Label: "uni-101", Type: voltha.Port_ETHERNET_UNI, AdminState: voltha.AdminState_ENABLED,
193 OperStatus: voltha.OperStatus_ACTIVE}
194 )
195 localWG.Add(1)
196 go func() {
197 deviceToUpdate := proto.Clone(originalDevice).(*voltha.Device)
198 deviceToUpdate.Root = root
199 deviceToUpdate.Vendor = vendor
200 deviceToUpdate.Model = model
201 deviceToUpdate.SerialNumber = serialNumber
202 deviceToUpdate.MacAddress = macAddress
203 deviceToUpdate.Vlan = vlan
204 deviceToUpdate.Reason = reason
npujar467fe752020-01-16 20:17:45 +0530205 err := da.updateDeviceUsingAdapterData(context.Background(), deviceToUpdate)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500206 assert.Nil(t, err)
207 localWG.Done()
208 }()
209
210 // Update the device status routine
211 localWG.Add(1)
212 go func() {
npujar467fe752020-01-16 20:17:45 +0530213 err := da.updateDeviceStatus(context.Background(), voltha.OperStatus_ACTIVE, voltha.ConnectStatus_REACHABLE)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500214 assert.Nil(t, err)
215 localWG.Done()
216 }()
217
218 // Add a port routine
219 localWG.Add(1)
220 go func() {
npujar467fe752020-01-16 20:17:45 +0530221 err := da.addPort(context.Background(), portToAdd)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500222 assert.Nil(t, err)
223 localWG.Done()
224 }()
225
226 // wait for go routines to be done
227 localWG.Wait()
228
229 expectedChange := proto.Clone(originalDevice).(*voltha.Device)
230 expectedChange.OperStatus = voltha.OperStatus_ACTIVE
231 expectedChange.ConnectStatus = voltha.ConnectStatus_REACHABLE
232 expectedChange.Ports = append(expectedChange.Ports, portToAdd)
233 expectedChange.Root = root
234 expectedChange.Vendor = vendor
235 expectedChange.Model = model
236 expectedChange.SerialNumber = serialNumber
237 expectedChange.MacAddress = macAddress
238 expectedChange.Vlan = vlan
239 expectedChange.Reason = reason
240
khenaidoo442e7c72020-03-10 16:13:48 -0400241 updatedDevice, _ := da.getDevice(context.Background())
khenaidoo6e55d9e2019-12-12 18:26:26 -0500242 assert.NotNil(t, updatedDevice)
243 assert.True(t, proto.Equal(expectedChange, updatedDevice))
244
245 globalWG.Done()
246}
247
248func TestConcurrentDevices(t *testing.T) {
khenaidoo442e7c72020-03-10 16:13:48 -0400249 for i := 0; i < 2; i++ {
250 da := newDATest()
251 assert.NotNil(t, da)
252 defer da.stopAll()
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700253 log.SetPackageLogLevel("github.com/opencord/voltha-go/rw_core/core", log.DebugLevel)
khenaidoo442e7c72020-03-10 16:13:48 -0400254 // Start the Core
255 da.startCore(false)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500256
khenaidoo442e7c72020-03-10 16:13:48 -0400257 var wg sync.WaitGroup
258 numConCurrentDeviceAgents := 20
259 for i := 0; i < numConCurrentDeviceAgents; i++ {
260 wg.Add(1)
261 a := da.createDeviceAgent(t)
262 go da.updateDeviceConcurrently(t, a, &wg)
263 }
264
265 wg.Wait()
khenaidoo6e55d9e2019-12-12 18:26:26 -0500266 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500267}
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700268func TestFlowUpdates(t *testing.T) {
269 da := newDATest()
270 assert.NotNil(t, da)
271 defer da.stopAll()
272
273 log.SetPackageLogLevel("github.com/opencord/voltha-go/rw_core/core", log.DebugLevel)
274 // Start the Core
275 da.startCore(false)
276 da.oltAdapter, da.onuAdapter = tst.CreateAndregisterAdapters(t, da.kClient, da.coreInstanceID, da.oltAdapterName, da.onuAdapterName, da.adapterMgr)
277
278 a := da.createDeviceAgent(t)
279 cloned := a.getDeviceWithoutLock()
280 err := a.updateDeviceStateInStoreWithoutLock(context.Background(), cloned, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
281 assert.Nil(t, err)
282 da.testFlowAddDeletes(t, a)
283}
284
285func TestGroupUpdates(t *testing.T) {
286 da := newDATest()
287 assert.NotNil(t, da)
288 defer da.stopAll()
289
290 // Start the Core
291 da.startCore(false)
292 da.oltAdapter, da.onuAdapter = tst.CreateAndregisterAdapters(t, da.kClient, da.coreInstanceID, da.oltAdapterName, da.onuAdapterName, da.adapterMgr)
293 a := da.createDeviceAgent(t)
294 cloned := a.getDeviceWithoutLock()
295 err := a.updateDeviceStateInStoreWithoutLock(context.Background(), cloned, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
296 assert.Nil(t, err)
297 da.testGroupAddDeletes(t, a)
298}
khenaidoob2121e52019-12-16 17:17:22 -0500299
300func isFlowSliceEqual(a, b []*ofp.OfpFlowStats) bool {
301 if len(a) != len(b) {
302 return false
303 }
304 sort.Slice(a, func(i, j int) bool {
305 return a[i].Id < a[j].Id
306 })
307 sort.Slice(b, func(i, j int) bool {
308 return b[i].Id < b[j].Id
309 })
310 for idx := range a {
311 if !proto.Equal(a[idx], b[idx]) {
312 return false
313 }
314 }
315 return true
316}
317
318func isGroupSliceEqual(a, b []*ofp.OfpGroupEntry) bool {
319 if len(a) != len(b) {
320 return false
321 }
322 sort.Slice(a, func(i, j int) bool {
323 return a[i].Desc.GroupId < a[j].Desc.GroupId
324 })
325 sort.Slice(b, func(i, j int) bool {
326 return b[i].Desc.GroupId < b[j].Desc.GroupId
327 })
328 for idx := range a {
329 if !proto.Equal(a[idx], b[idx]) {
330 return false
331 }
332 }
333 return true
334}
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700335func changeToFlowList(flowList map[uint64]*ofp.OfpFlowStats) []*ofp.OfpFlowStats {
336 flows := make([]*ofp.OfpFlowStats, 0)
337 for _, flow := range flowList {
338 flows = append(flows, flow)
339 }
340 return flows
khenaidoob2121e52019-12-16 17:17:22 -0500341}
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700342func changeToGroupList(groupList map[uint32]*ofp.OfpGroupEntry) []*ofp.OfpGroupEntry {
343 groups := make([]*ofp.OfpGroupEntry, 0)
344 for _, group := range groupList {
345 groups = append(groups, group)
346 }
347 return groups
348}
349func (dat *DATest) testFlowAddDeletes(t *testing.T, da *Agent) {
350 //Add new Flows on empty list
khenaidoob2121e52019-12-16 17:17:22 -0500351 newFlows := []*ofp.OfpFlowStats{
352 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
353 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
354 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
355 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700356 err := da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
357 assert.Nil(t, err)
358 daFlows := changeToFlowList(da.listDeviceFlows())
359 assert.True(t, isFlowSliceEqual(newFlows, daFlows))
khenaidoob2121e52019-12-16 17:17:22 -0500360
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700361 //Add new Flows on existing ones
362 newFlows = []*ofp.OfpFlowStats{
363 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500364 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270000, PacketCount: 0},
365 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700366
367 expectedFlows := []*ofp.OfpFlowStats{
368 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
369 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
370 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
371 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
372 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270000, PacketCount: 0},
373 }
374
375 err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
376 assert.Nil(t, err)
377 daFlows = changeToFlowList(da.listDeviceFlows())
378 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
379
380 //Add existing Flows again with a new flow
381 newFlows = []*ofp.OfpFlowStats{
382 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
383 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
384 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
385 }
386
387 expectedFlows = []*ofp.OfpFlowStats{
388 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
389 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
390 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
391 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
392 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
393 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
394 }
395
396 err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
397 assert.Nil(t, err)
398 daFlows = changeToFlowList(da.listDeviceFlows())
399 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
400
401 //Add already existing flows again
402 newFlows = []*ofp.OfpFlowStats{
403 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
404 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
405 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
406 }
407
408 expectedFlows = []*ofp.OfpFlowStats{
409 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
410 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
411 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
412 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
413 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
414 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
415 }
416
417 err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
418 assert.Nil(t, err)
419 daFlows = changeToFlowList(da.listDeviceFlows())
420 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
421
422 //Delete flows
423 flowsToDelete := []*ofp.OfpFlowStats{
424 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
425 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
426 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
427 }
428
429 expectedFlows = []*ofp.OfpFlowStats{
khenaidoob2121e52019-12-16 17:17:22 -0500430 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
431 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
432 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
433 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700434
435 err = da.deleteFlowsAndGroups(context.Background(), flowsToDelete, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
436 assert.Nil(t, err)
437 daFlows = changeToFlowList(da.listDeviceFlows())
438 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
439 //Delete flows with an unexisting one
440 flowsToDelete = []*ofp.OfpFlowStats{
khenaidoob2121e52019-12-16 17:17:22 -0500441 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700442 {Id: 129, TableId: 1290, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1290000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500443 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700444
445 expectedFlows = []*ofp.OfpFlowStats{
446 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500447 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500448 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700449
450 err = da.deleteFlowsAndGroups(context.Background(), flowsToDelete, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
451 assert.Nil(t, err)
452 daFlows = changeToFlowList(da.listDeviceFlows())
453 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
khenaidoob2121e52019-12-16 17:17:22 -0500454}
455
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700456func (dat *DATest) testGroupAddDeletes(t *testing.T, da *Agent) {
457 //Add new Groups on empty list
khenaidoob2121e52019-12-16 17:17:22 -0500458 newGroups := []*ofp.OfpGroupEntry{
459 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
460 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
461 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700462 err := da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
463 assert.Nil(t, err)
464 daGroups := changeToGroupList(da.listDeviceGroups())
465 assert.True(t, isGroupSliceEqual(newGroups, daGroups))
khenaidoob2121e52019-12-16 17:17:22 -0500466
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700467 //Add new Groups on existing ones
468 newGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500469 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
470 {Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, Buckets: nil}},
471 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700472 expectedGroups := []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500473 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
474 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
475 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
476 {Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, Buckets: nil}},
477 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700478 err = da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
479 assert.Nil(t, err)
480 daGroups = changeToGroupList(da.listDeviceGroups())
481 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
khenaidoob2121e52019-12-16 17:17:22 -0500482
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700483 //Add new Groups on existing ones
484 newGroups = []*ofp.OfpGroupEntry{
485 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
486 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
487 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500488 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700489 expectedGroups = []*ofp.OfpGroupEntry{
490 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500491 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
492 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700493 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
494 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500495 }
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))
500
501 //Modify Group
502 updtGroups := []*ofp.OfpGroupEntry{
503 {Desc: &ofp.OfpGroupDesc{Type: 33, GroupId: 30, Buckets: nil}},
504 }
505 expectedGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500506 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500507 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700508 {Desc: &ofp.OfpGroupDesc{Type: 33, GroupId: 30, Buckets: nil}},
509 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
510 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500511 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700512 err = da.updateFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, updtGroups, &voltha.FlowMetadata{})
513 assert.Nil(t, err)
514 daGroups = changeToGroupList(da.listDeviceGroups())
515 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
516
517 //Delete Group
518 delGroups := []*ofp.OfpGroupEntry{
519 {Desc: &ofp.OfpGroupDesc{Type: 33, GroupId: 30, Buckets: nil}},
520 }
521 expectedGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500522 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700523 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
524 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
525 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
526 }
527 err = da.deleteFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, delGroups, &voltha.FlowMetadata{})
528 assert.Nil(t, err)
529 daGroups = changeToGroupList(da.listDeviceGroups())
530 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
531
532 //Delete Group
533 delGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500534 {Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, Buckets: nil}},
535 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700536 expectedGroups = []*ofp.OfpGroupEntry{
537 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
538 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
539 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
540 }
541 err = da.deleteFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, delGroups, &voltha.FlowMetadata{})
542 assert.Nil(t, err)
543 daGroups = changeToGroupList(da.listDeviceGroups())
544 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
khenaidoob2121e52019-12-16 17:17:22 -0500545}