blob: cd496817c6a0c98e7aba23f87b22fa08319eec17 [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()
serkant.uluderya8ff291d2020-05-20 00:58:00 -0700115 cfg.CoreTopic = "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,
serkant.uluderya8ff291d2020-05-20 00:58:00 -0700132 LivenessChannelInterval: cfg.LiveProbeInterval / 2}
Kent Hagerman2b216042020-04-03 18:28:56 -0400133 dat.kmp = kafka.NewInterContainerProxy(
134 kafka.InterContainerHost(cfg.KafkaAdapterHost),
135 kafka.InterContainerPort(cfg.KafkaAdapterPort),
136 kafka.MsgClient(dat.kClient),
137 kafka.DefaultTopic(&kafka.Topic{Name: cfg.CoreTopic}),
138 kafka.DeviceDiscoveryTopic(&kafka.Topic{Name: cfg.AffinityRouterTopic}))
139
140 endpointMgr := kafka.NewEndpointManager(backend)
Kent Hagermanf5a67352020-04-30 15:15:26 -0400141 proxy := model.NewDBPath(backend)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700142 dat.adapterMgr = adapter.NewAdapterManager(proxy, dat.coreInstanceID, dat.kClient)
Kent Hagerman2b216042020-04-03 18:28:56 -0400143
serkant.uluderya8ff291d2020-05-20 00:58:00 -0700144 dat.deviceMgr, dat.logicalDeviceMgr = NewManagers(proxy, dat.adapterMgr, dat.kmp, endpointMgr, cfg.CoreTopic, dat.coreInstanceID, cfg.DefaultCoreTimeout)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700145 dat.adapterMgr.Start(context.Background())
Kent Hagerman2b216042020-04-03 18:28:56 -0400146 if err = dat.kmp.Start(); err != nil {
147 logger.Fatal("Cannot start InterContainerProxy")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530148 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700149
serkant.uluderya8ff291d2020-05-20 00:58:00 -0700150 if err := dat.kmp.SubscribeWithDefaultRequestHandler(kafka.Topic{Name: cfg.CoreTopic}, kafka.OffsetNewest); err != nil {
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700151 logger.Fatalf("Cannot add default request handler: %s", err)
152 }
153
khenaidoo6e55d9e2019-12-12 18:26:26 -0500154}
155
156func (dat *DATest) stopAll() {
157 if dat.kClient != nil {
158 dat.kClient.Stop()
159 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400160 if dat.kmp != nil {
161 dat.kmp.Stop()
khenaidoo6e55d9e2019-12-12 18:26:26 -0500162 }
163 if dat.etcdServer != nil {
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700164 tst.StopEmbeddedEtcdServer(dat.etcdServer)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500165 }
166}
167
Kent Hagerman2b216042020-04-03 18:28:56 -0400168func (dat *DATest) createDeviceAgent(t *testing.T) *Agent {
169 deviceMgr := dat.deviceMgr
khenaidoo6e55d9e2019-12-12 18:26:26 -0500170 clonedDevice := proto.Clone(dat.device).(*voltha.Device)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700171 deviceAgent := newAgent(deviceMgr.adapterProxy, clonedDevice, deviceMgr, deviceMgr.dbPath, deviceMgr.dProxy, deviceMgr.defaultTimeout)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500172 d, err := deviceAgent.start(context.TODO(), clonedDevice)
173 assert.Nil(t, err)
174 assert.NotNil(t, d)
175 deviceMgr.addDeviceAgentToMap(deviceAgent)
176 return deviceAgent
177}
178
Kent Hagerman2b216042020-04-03 18:28:56 -0400179func (dat *DATest) updateDeviceConcurrently(t *testing.T, da *Agent, globalWG *sync.WaitGroup) {
khenaidoo442e7c72020-03-10 16:13:48 -0400180 originalDevice, err := da.getDevice(context.Background())
181 assert.Nil(t, err)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500182 assert.NotNil(t, originalDevice)
183 var localWG sync.WaitGroup
184
185 // Update device routine
186 var (
187 root = false
188 vendor = "onu_adapter_mock"
189 model = "go-mock"
190 serialNumber = com.GetRandomSerialNumber()
191 macAddress = strings.ToUpper(com.GetRandomMacAddress())
192 vlan = rand.Uint32()
193 reason = "testing concurrent device update"
194 portToAdd = &voltha.Port{PortNo: 101, Label: "uni-101", Type: voltha.Port_ETHERNET_UNI, AdminState: voltha.AdminState_ENABLED,
195 OperStatus: voltha.OperStatus_ACTIVE}
196 )
197 localWG.Add(1)
198 go func() {
199 deviceToUpdate := proto.Clone(originalDevice).(*voltha.Device)
200 deviceToUpdate.Root = root
201 deviceToUpdate.Vendor = vendor
202 deviceToUpdate.Model = model
203 deviceToUpdate.SerialNumber = serialNumber
204 deviceToUpdate.MacAddress = macAddress
205 deviceToUpdate.Vlan = vlan
206 deviceToUpdate.Reason = reason
npujar467fe752020-01-16 20:17:45 +0530207 err := da.updateDeviceUsingAdapterData(context.Background(), deviceToUpdate)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500208 assert.Nil(t, err)
209 localWG.Done()
210 }()
211
212 // Update the device status routine
213 localWG.Add(1)
214 go func() {
npujar467fe752020-01-16 20:17:45 +0530215 err := da.updateDeviceStatus(context.Background(), voltha.OperStatus_ACTIVE, voltha.ConnectStatus_REACHABLE)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500216 assert.Nil(t, err)
217 localWG.Done()
218 }()
219
220 // Add a port routine
221 localWG.Add(1)
222 go func() {
npujar467fe752020-01-16 20:17:45 +0530223 err := da.addPort(context.Background(), portToAdd)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500224 assert.Nil(t, err)
225 localWG.Done()
226 }()
227
228 // wait for go routines to be done
229 localWG.Wait()
230
231 expectedChange := proto.Clone(originalDevice).(*voltha.Device)
232 expectedChange.OperStatus = voltha.OperStatus_ACTIVE
233 expectedChange.ConnectStatus = voltha.ConnectStatus_REACHABLE
234 expectedChange.Ports = append(expectedChange.Ports, portToAdd)
235 expectedChange.Root = root
236 expectedChange.Vendor = vendor
237 expectedChange.Model = model
238 expectedChange.SerialNumber = serialNumber
239 expectedChange.MacAddress = macAddress
240 expectedChange.Vlan = vlan
241 expectedChange.Reason = reason
242
khenaidoo442e7c72020-03-10 16:13:48 -0400243 updatedDevice, _ := da.getDevice(context.Background())
khenaidoo6e55d9e2019-12-12 18:26:26 -0500244 assert.NotNil(t, updatedDevice)
245 assert.True(t, proto.Equal(expectedChange, updatedDevice))
246
247 globalWG.Done()
248}
249
250func TestConcurrentDevices(t *testing.T) {
khenaidoo442e7c72020-03-10 16:13:48 -0400251 for i := 0; i < 2; i++ {
252 da := newDATest()
253 assert.NotNil(t, da)
254 defer da.stopAll()
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700255 log.SetPackageLogLevel("github.com/opencord/voltha-go/rw_core/core", log.DebugLevel)
khenaidoo442e7c72020-03-10 16:13:48 -0400256 // Start the Core
257 da.startCore(false)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500258
khenaidoo442e7c72020-03-10 16:13:48 -0400259 var wg sync.WaitGroup
260 numConCurrentDeviceAgents := 20
261 for i := 0; i < numConCurrentDeviceAgents; i++ {
262 wg.Add(1)
263 a := da.createDeviceAgent(t)
264 go da.updateDeviceConcurrently(t, a, &wg)
265 }
266
267 wg.Wait()
khenaidoo6e55d9e2019-12-12 18:26:26 -0500268 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500269}
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700270func TestFlowUpdates(t *testing.T) {
271 da := newDATest()
272 assert.NotNil(t, da)
273 defer da.stopAll()
274
275 log.SetPackageLogLevel("github.com/opencord/voltha-go/rw_core/core", log.DebugLevel)
276 // Start the Core
277 da.startCore(false)
278 da.oltAdapter, da.onuAdapter = tst.CreateAndregisterAdapters(t, da.kClient, da.coreInstanceID, da.oltAdapterName, da.onuAdapterName, da.adapterMgr)
279
280 a := da.createDeviceAgent(t)
281 cloned := a.getDeviceWithoutLock()
282 err := a.updateDeviceStateInStoreWithoutLock(context.Background(), cloned, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
283 assert.Nil(t, err)
284 da.testFlowAddDeletes(t, a)
285}
286
287func TestGroupUpdates(t *testing.T) {
288 da := newDATest()
289 assert.NotNil(t, da)
290 defer da.stopAll()
291
292 // Start the Core
293 da.startCore(false)
294 da.oltAdapter, da.onuAdapter = tst.CreateAndregisterAdapters(t, da.kClient, da.coreInstanceID, da.oltAdapterName, da.onuAdapterName, da.adapterMgr)
295 a := da.createDeviceAgent(t)
296 cloned := a.getDeviceWithoutLock()
297 err := a.updateDeviceStateInStoreWithoutLock(context.Background(), cloned, voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE)
298 assert.Nil(t, err)
299 da.testGroupAddDeletes(t, a)
300}
khenaidoob2121e52019-12-16 17:17:22 -0500301
302func isFlowSliceEqual(a, b []*ofp.OfpFlowStats) bool {
303 if len(a) != len(b) {
304 return false
305 }
306 sort.Slice(a, func(i, j int) bool {
307 return a[i].Id < a[j].Id
308 })
309 sort.Slice(b, func(i, j int) bool {
310 return b[i].Id < b[j].Id
311 })
312 for idx := range a {
313 if !proto.Equal(a[idx], b[idx]) {
314 return false
315 }
316 }
317 return true
318}
319
320func isGroupSliceEqual(a, b []*ofp.OfpGroupEntry) bool {
321 if len(a) != len(b) {
322 return false
323 }
324 sort.Slice(a, func(i, j int) bool {
325 return a[i].Desc.GroupId < a[j].Desc.GroupId
326 })
327 sort.Slice(b, func(i, j int) bool {
328 return b[i].Desc.GroupId < b[j].Desc.GroupId
329 })
330 for idx := range a {
331 if !proto.Equal(a[idx], b[idx]) {
332 return false
333 }
334 }
335 return true
336}
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700337func changeToFlowList(flowList map[uint64]*ofp.OfpFlowStats) []*ofp.OfpFlowStats {
338 flows := make([]*ofp.OfpFlowStats, 0)
339 for _, flow := range flowList {
340 flows = append(flows, flow)
341 }
342 return flows
khenaidoob2121e52019-12-16 17:17:22 -0500343}
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700344func changeToGroupList(groupList map[uint32]*ofp.OfpGroupEntry) []*ofp.OfpGroupEntry {
345 groups := make([]*ofp.OfpGroupEntry, 0)
346 for _, group := range groupList {
347 groups = append(groups, group)
348 }
349 return groups
350}
351func (dat *DATest) testFlowAddDeletes(t *testing.T, da *Agent) {
352 //Add new Flows on empty list
khenaidoob2121e52019-12-16 17:17:22 -0500353 newFlows := []*ofp.OfpFlowStats{
354 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
355 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
356 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
357 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700358 err := da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
359 assert.Nil(t, err)
360 daFlows := changeToFlowList(da.listDeviceFlows())
361 assert.True(t, isFlowSliceEqual(newFlows, daFlows))
khenaidoob2121e52019-12-16 17:17:22 -0500362
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700363 //Add new Flows on existing ones
364 newFlows = []*ofp.OfpFlowStats{
365 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500366 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270000, PacketCount: 0},
367 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700368
369 expectedFlows := []*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 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
374 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270000, PacketCount: 0},
375 }
376
377 err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
378 assert.Nil(t, err)
379 daFlows = changeToFlowList(da.listDeviceFlows())
380 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
381
382 //Add existing Flows again with a new flow
383 newFlows = []*ofp.OfpFlowStats{
384 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
385 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
386 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
387 }
388
389 expectedFlows = []*ofp.OfpFlowStats{
390 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
391 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
392 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
393 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
394 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
395 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
396 }
397
398 err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
399 assert.Nil(t, err)
400 daFlows = changeToFlowList(da.listDeviceFlows())
401 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
402
403 //Add already existing flows again
404 newFlows = []*ofp.OfpFlowStats{
405 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
406 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
407 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
408 }
409
410 expectedFlows = []*ofp.OfpFlowStats{
411 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
412 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
413 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
414 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
415 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
416 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
417 }
418
419 err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
420 assert.Nil(t, err)
421 daFlows = changeToFlowList(da.listDeviceFlows())
422 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
423
424 //Delete flows
425 flowsToDelete := []*ofp.OfpFlowStats{
426 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
427 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
428 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
429 }
430
431 expectedFlows = []*ofp.OfpFlowStats{
khenaidoob2121e52019-12-16 17:17:22 -0500432 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
433 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
434 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
435 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700436
437 err = da.deleteFlowsAndGroups(context.Background(), flowsToDelete, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
438 assert.Nil(t, err)
439 daFlows = changeToFlowList(da.listDeviceFlows())
440 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
441 //Delete flows with an unexisting one
442 flowsToDelete = []*ofp.OfpFlowStats{
khenaidoob2121e52019-12-16 17:17:22 -0500443 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700444 {Id: 129, TableId: 1290, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1290000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500445 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700446
447 expectedFlows = []*ofp.OfpFlowStats{
448 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500449 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500450 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700451
452 err = da.deleteFlowsAndGroups(context.Background(), flowsToDelete, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
453 assert.Nil(t, err)
454 daFlows = changeToFlowList(da.listDeviceFlows())
455 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
khenaidoob2121e52019-12-16 17:17:22 -0500456}
457
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700458func (dat *DATest) testGroupAddDeletes(t *testing.T, da *Agent) {
459 //Add new Groups on empty list
khenaidoob2121e52019-12-16 17:17:22 -0500460 newGroups := []*ofp.OfpGroupEntry{
461 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
462 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
463 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700464 err := da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
465 assert.Nil(t, err)
466 daGroups := changeToGroupList(da.listDeviceGroups())
467 assert.True(t, isGroupSliceEqual(newGroups, daGroups))
khenaidoob2121e52019-12-16 17:17:22 -0500468
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700469 //Add new Groups on existing ones
470 newGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500471 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
472 {Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, Buckets: nil}},
473 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700474 expectedGroups := []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500475 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
476 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
477 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
478 {Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, 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(expectedGroups, 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{
487 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
488 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
489 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500490 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700491 expectedGroups = []*ofp.OfpGroupEntry{
492 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500493 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
494 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700495 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
496 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500497 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700498 err = da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
499 assert.Nil(t, err)
500 daGroups = changeToGroupList(da.listDeviceGroups())
501 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
502
503 //Modify Group
504 updtGroups := []*ofp.OfpGroupEntry{
505 {Desc: &ofp.OfpGroupDesc{Type: 33, GroupId: 30, Buckets: nil}},
506 }
507 expectedGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500508 {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}},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700510 {Desc: &ofp.OfpGroupDesc{Type: 33, GroupId: 30, Buckets: nil}},
511 {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.updateFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, updtGroups, &voltha.FlowMetadata{})
515 assert.Nil(t, err)
516 daGroups = changeToGroupList(da.listDeviceGroups())
517 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
518
519 //Delete Group
520 delGroups := []*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}},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700525 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
526 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
527 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
528 }
529 err = da.deleteFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, delGroups, &voltha.FlowMetadata{})
530 assert.Nil(t, err)
531 daGroups = changeToGroupList(da.listDeviceGroups())
532 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
533
534 //Delete Group
535 delGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500536 {Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, Buckets: nil}},
537 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700538 expectedGroups = []*ofp.OfpGroupEntry{
539 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
540 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
541 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
542 }
543 err = da.deleteFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, delGroups, &voltha.FlowMetadata{})
544 assert.Nil(t, err)
545 daGroups = changeToGroupList(da.listDeviceGroups())
546 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
khenaidoob2121e52019-12-16 17:17:22 -0500547}