blob: daf2508f8bbe9b3bf9d835103cdb9f774998b606 [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"
Maninderdfadc982020-10-28 14:04:33 +053036 com "github.com/opencord/voltha-lib-go/v4/pkg/adapters/common"
37 "github.com/opencord/voltha-lib-go/v4/pkg/db"
Himani Chawlab4c25912020-11-12 17:16:38 +053038 "github.com/opencord/voltha-lib-go/v4/pkg/events"
Maninderdfadc982020-10-28 14:04:33 +053039 "github.com/opencord/voltha-lib-go/v4/pkg/kafka"
40 "github.com/opencord/voltha-lib-go/v4/pkg/log"
41 mock_etcd "github.com/opencord/voltha-lib-go/v4/pkg/mocks/etcd"
42 mock_kafka "github.com/opencord/voltha-lib-go/v4/pkg/mocks/kafka"
43 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
44 "github.com/opencord/voltha-protos/v4/go/voltha"
khenaidoo6e55d9e2019-12-12 18:26:26 -050045 "github.com/phayes/freeport"
46 "github.com/stretchr/testify/assert"
khenaidoo6e55d9e2019-12-12 18:26:26 -050047)
48
49type DATest struct {
Kent Hagerman2b216042020-04-03 18:28:56 -040050 etcdServer *mock_etcd.EtcdServer
51 deviceMgr *Manager
52 logicalDeviceMgr *LogicalManager
Mahir Gunyel03de0d32020-06-03 01:36:59 -070053 adapterMgr *adapter.Manager
Kent Hagerman2b216042020-04-03 18:28:56 -040054 kmp kafka.InterContainerProxy
55 kClient kafka.Client
Himani Chawlab4c25912020-11-12 17:16:38 +053056 kEventClient kafka.Client
Kent Hagerman2b216042020-04-03 18:28:56 -040057 kvClientPort int
Mahir Gunyel03de0d32020-06-03 01:36:59 -070058 oltAdapter *cm.OLTAdapter
59 onuAdapter *cm.ONUAdapter
Kent Hagerman2b216042020-04-03 18:28:56 -040060 oltAdapterName string
61 onuAdapterName string
62 coreInstanceID string
63 defaultTimeout time.Duration
64 maxTimeout time.Duration
65 device *voltha.Device
Kent Hagerman2a07b862020-06-19 15:23:07 -040066 devicePorts map[uint32]*voltha.Port
Kent Hagerman2b216042020-04-03 18:28:56 -040067 done chan int
khenaidoo6e55d9e2019-12-12 18:26:26 -050068}
69
Rohan Agrawal31f21802020-06-12 05:38:46 +000070func newDATest(ctx context.Context) *DATest {
khenaidoo6e55d9e2019-12-12 18:26:26 -050071 test := &DATest{}
72 // Start the embedded etcd server
73 var err error
Rohan Agrawal31f21802020-06-12 05:38:46 +000074 test.etcdServer, test.kvClientPort, err = tst.StartEmbeddedEtcdServer(ctx, "voltha.rwcore.da.test", "voltha.rwcore.da.etcd", "error")
khenaidoo6e55d9e2019-12-12 18:26:26 -050075 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +000076 logger.Fatal(ctx, err)
khenaidoo6e55d9e2019-12-12 18:26:26 -050077 }
78 // Create the kafka client
Matteo Scandolod525ae32020-04-02 17:27:29 -070079 test.kClient = mock_kafka.NewKafkaClient()
Himani Chawlab4c25912020-11-12 17:16:38 +053080 test.kEventClient = mock_kafka.NewKafkaClient()
khenaidoo6e55d9e2019-12-12 18:26:26 -050081 test.oltAdapterName = "olt_adapter_mock"
82 test.onuAdapterName = "onu_adapter_mock"
83 test.coreInstanceID = "rw-da-test"
84 test.defaultTimeout = 5 * time.Second
85 test.maxTimeout = 20 * time.Second
86 test.done = make(chan int)
87 parentID := com.GetRandomString(10)
88 test.device = &voltha.Device{
89 Type: "onu_adapter_mock",
90 ParentId: parentID,
91 ParentPortNo: 1,
92 VendorId: "onu_adapter_mock",
93 Adapter: "onu_adapter_mock",
94 Vlan: 100,
95 Address: nil,
96 ProxyAddress: &voltha.Device_ProxyAddress{
97 DeviceId: parentID,
98 DeviceType: "olt_adapter_mock",
99 ChannelId: 100,
100 ChannelGroupId: 0,
101 ChannelTermination: "",
102 OnuId: 2,
103 },
104 AdminState: voltha.AdminState_PREPROVISIONED,
105 OperStatus: voltha.OperStatus_UNKNOWN,
106 Reason: "All good",
107 ConnectStatus: voltha.ConnectStatus_UNKNOWN,
108 Custom: nil,
Kent Hagerman2a07b862020-06-19 15:23:07 -0400109 }
110 test.devicePorts = map[uint32]*voltha.Port{
111 1: {PortNo: 1, Label: "pon-1", Type: voltha.Port_PON_ONU, AdminState: voltha.AdminState_ENABLED,
112 OperStatus: voltha.OperStatus_ACTIVE, Peers: []*voltha.Port_PeerPort{{DeviceId: parentID, PortNo: 1}}},
113 100: {PortNo: 100, Label: "uni-100", Type: voltha.Port_ETHERNET_UNI, AdminState: voltha.AdminState_ENABLED,
114 OperStatus: voltha.OperStatus_ACTIVE},
khenaidoo6e55d9e2019-12-12 18:26:26 -0500115 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500116 return test
117}
118
Rohan Agrawal31f21802020-06-12 05:38:46 +0000119func (dat *DATest) startCore(ctx context.Context) {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500120 cfg := config.NewRWCoreFlags()
serkant.uluderya8ff291d2020-05-20 00:58:00 -0700121 cfg.CoreTopic = "rw_core"
Himani Chawlab4c25912020-11-12 17:16:38 +0530122 cfg.EventTopic = "voltha.events"
khenaidoo442e7c72020-03-10 16:13:48 -0400123 cfg.DefaultRequestTimeout = dat.defaultTimeout
Neha Sharmad1387da2020-05-07 20:07:28 +0000124 cfg.KVStoreAddress = "127.0.0.1" + ":" + strconv.Itoa(dat.kvClientPort)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500125 grpcPort, err := freeport.GetFreePort()
126 if err != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000127 logger.Fatal(ctx, "Cannot get a freeport for grpc")
khenaidoo6e55d9e2019-12-12 18:26:26 -0500128 }
Neha Sharmad1387da2020-05-07 20:07:28 +0000129 cfg.GrpcAddress = "127.0.0.1" + ":" + strconv.Itoa(grpcPort)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000130 client := tst.SetupKVClient(ctx, cfg, dat.coreInstanceID)
Kent Hagerman2b216042020-04-03 18:28:56 -0400131 backend := &db.Backend{
132 Client: client,
133 StoreType: cfg.KVStoreType,
Neha Sharmad1387da2020-05-07 20:07:28 +0000134 Address: cfg.KVStoreAddress,
Kent Hagerman2b216042020-04-03 18:28:56 -0400135 Timeout: cfg.KVStoreTimeout,
serkant.uluderya8ff291d2020-05-20 00:58:00 -0700136 LivenessChannelInterval: cfg.LiveProbeInterval / 2}
Kent Hagerman2b216042020-04-03 18:28:56 -0400137 dat.kmp = kafka.NewInterContainerProxy(
Neha Sharmad1387da2020-05-07 20:07:28 +0000138 kafka.InterContainerAddress(cfg.KafkaAdapterAddress),
Kent Hagerman2b216042020-04-03 18:28:56 -0400139 kafka.MsgClient(dat.kClient),
David Bainbridge9ae13132020-06-22 17:28:01 -0700140 kafka.DefaultTopic(&kafka.Topic{Name: cfg.CoreTopic}))
Kent Hagerman2b216042020-04-03 18:28:56 -0400141
142 endpointMgr := kafka.NewEndpointManager(backend)
Kent Hagermanf5a67352020-04-30 15:15:26 -0400143 proxy := model.NewDBPath(backend)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000144 dat.adapterMgr = adapter.NewAdapterManager(ctx, proxy, dat.coreInstanceID, dat.kClient)
Himani Chawlab4c25912020-11-12 17:16:38 +0530145 eventProxy := events.NewEventProxy(events.MsgClient(dat.kEventClient), events.MsgTopic(kafka.Topic{Name: cfg.EventTopic}))
Maninder0aabf0c2021-03-17 14:55:14 +0530146 dat.deviceMgr, dat.logicalDeviceMgr = NewManagers(proxy, dat.adapterMgr, dat.kmp, endpointMgr, cfg, dat.coreInstanceID, eventProxy)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700147 dat.adapterMgr.Start(context.Background())
Rohan Agrawal31f21802020-06-12 05:38:46 +0000148 if err = dat.kmp.Start(ctx); err != nil {
149 logger.Fatal(ctx, "Cannot start InterContainerProxy")
Thomas Lee Se5a44012019-11-07 20:32:24 +0530150 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700151
Rohan Agrawal31f21802020-06-12 05:38:46 +0000152 if err := dat.kmp.SubscribeWithDefaultRequestHandler(ctx, kafka.Topic{Name: cfg.CoreTopic}, kafka.OffsetNewest); err != nil {
153 logger.Fatalf(ctx, "Cannot add default request handler: %s", err)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700154 }
155
khenaidoo6e55d9e2019-12-12 18:26:26 -0500156}
157
Rohan Agrawal31f21802020-06-12 05:38:46 +0000158func (dat *DATest) stopAll(ctx context.Context) {
khenaidoo6e55d9e2019-12-12 18:26:26 -0500159 if dat.kClient != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000160 dat.kClient.Stop(ctx)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500161 }
Kent Hagerman2b216042020-04-03 18:28:56 -0400162 if dat.kmp != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000163 dat.kmp.Stop(ctx)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500164 }
165 if dat.etcdServer != nil {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000166 tst.StopEmbeddedEtcdServer(ctx, dat.etcdServer)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500167 }
Himani Chawlab4c25912020-11-12 17:16:38 +0530168 if dat.kEventClient != nil {
169 dat.kEventClient.Stop(ctx)
170 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500171}
172
Kent Hagerman2b216042020-04-03 18:28:56 -0400173func (dat *DATest) createDeviceAgent(t *testing.T) *Agent {
174 deviceMgr := dat.deviceMgr
khenaidoo6e55d9e2019-12-12 18:26:26 -0500175 clonedDevice := proto.Clone(dat.device).(*voltha.Device)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700176 deviceAgent := newAgent(deviceMgr.adapterProxy, clonedDevice, deviceMgr, deviceMgr.dbPath, deviceMgr.dProxy, deviceMgr.defaultTimeout)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500177 d, err := deviceAgent.start(context.TODO(), clonedDevice)
178 assert.Nil(t, err)
179 assert.NotNil(t, d)
Kent Hagerman2a07b862020-06-19 15:23:07 -0400180 for _, port := range dat.devicePorts {
181 err := deviceAgent.addPort(context.TODO(), port)
182 assert.Nil(t, err)
183 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500184 deviceMgr.addDeviceAgentToMap(deviceAgent)
185 return deviceAgent
186}
187
Kent Hagerman2b216042020-04-03 18:28:56 -0400188func (dat *DATest) updateDeviceConcurrently(t *testing.T, da *Agent, globalWG *sync.WaitGroup) {
Kent Hagermancba2f302020-07-28 13:37:36 -0400189 originalDevice, err := da.getDeviceReadOnly(context.Background())
Kent Hagerman2a07b862020-06-19 15:23:07 -0400190 originalDevicePorts := da.listDevicePorts()
khenaidoo442e7c72020-03-10 16:13:48 -0400191 assert.Nil(t, err)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500192 assert.NotNil(t, originalDevice)
193 var localWG sync.WaitGroup
194
195 // Update device routine
196 var (
197 root = false
198 vendor = "onu_adapter_mock"
199 model = "go-mock"
200 serialNumber = com.GetRandomSerialNumber()
201 macAddress = strings.ToUpper(com.GetRandomMacAddress())
202 vlan = rand.Uint32()
203 reason = "testing concurrent device update"
204 portToAdd = &voltha.Port{PortNo: 101, Label: "uni-101", Type: voltha.Port_ETHERNET_UNI, AdminState: voltha.AdminState_ENABLED,
205 OperStatus: voltha.OperStatus_ACTIVE}
206 )
207 localWG.Add(1)
208 go func() {
209 deviceToUpdate := proto.Clone(originalDevice).(*voltha.Device)
210 deviceToUpdate.Root = root
211 deviceToUpdate.Vendor = vendor
212 deviceToUpdate.Model = model
213 deviceToUpdate.SerialNumber = serialNumber
214 deviceToUpdate.MacAddress = macAddress
215 deviceToUpdate.Vlan = vlan
216 deviceToUpdate.Reason = reason
npujar467fe752020-01-16 20:17:45 +0530217 err := da.updateDeviceUsingAdapterData(context.Background(), deviceToUpdate)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500218 assert.Nil(t, err)
219 localWG.Done()
220 }()
221
222 // Update the device status routine
223 localWG.Add(1)
224 go func() {
npujar467fe752020-01-16 20:17:45 +0530225 err := da.updateDeviceStatus(context.Background(), voltha.OperStatus_ACTIVE, voltha.ConnectStatus_REACHABLE)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500226 assert.Nil(t, err)
227 localWG.Done()
228 }()
229
230 // Add a port routine
231 localWG.Add(1)
232 go func() {
npujar467fe752020-01-16 20:17:45 +0530233 err := da.addPort(context.Background(), portToAdd)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500234 assert.Nil(t, err)
235 localWG.Done()
236 }()
237
238 // wait for go routines to be done
239 localWG.Wait()
240
241 expectedChange := proto.Clone(originalDevice).(*voltha.Device)
242 expectedChange.OperStatus = voltha.OperStatus_ACTIVE
243 expectedChange.ConnectStatus = voltha.ConnectStatus_REACHABLE
khenaidoo6e55d9e2019-12-12 18:26:26 -0500244 expectedChange.Root = root
245 expectedChange.Vendor = vendor
246 expectedChange.Model = model
247 expectedChange.SerialNumber = serialNumber
248 expectedChange.MacAddress = macAddress
249 expectedChange.Vlan = vlan
250 expectedChange.Reason = reason
251
Kent Hagermancba2f302020-07-28 13:37:36 -0400252 updatedDevice, _ := da.getDeviceReadOnly(context.Background())
Kent Hagerman2a07b862020-06-19 15:23:07 -0400253 updatedDevicePorts := da.listDevicePorts()
khenaidoo6e55d9e2019-12-12 18:26:26 -0500254 assert.NotNil(t, updatedDevice)
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400255 fmt.Printf("1 %+v\n", expectedChange)
256 fmt.Printf("2 %+v\n", updatedDevice)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500257 assert.True(t, proto.Equal(expectedChange, updatedDevice))
Kent Hagerman2a07b862020-06-19 15:23:07 -0400258 assert.Equal(t, len(originalDevicePorts)+1, len(updatedDevicePorts))
259 assert.True(t, proto.Equal(updatedDevicePorts[portToAdd.PortNo], portToAdd))
khenaidoo6e55d9e2019-12-12 18:26:26 -0500260
261 globalWG.Done()
262}
263
264func TestConcurrentDevices(t *testing.T) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000265 ctx := context.Background()
khenaidoo442e7c72020-03-10 16:13:48 -0400266 for i := 0; i < 2; i++ {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000267 da := newDATest(ctx)
khenaidoo442e7c72020-03-10 16:13:48 -0400268 assert.NotNil(t, da)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000269 defer da.stopAll(ctx)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700270 log.SetPackageLogLevel("github.com/opencord/voltha-go/rw_core/core", log.DebugLevel)
khenaidoo442e7c72020-03-10 16:13:48 -0400271 // Start the Core
Rohan Agrawal31f21802020-06-12 05:38:46 +0000272 da.startCore(ctx)
khenaidoo6e55d9e2019-12-12 18:26:26 -0500273
khenaidoo442e7c72020-03-10 16:13:48 -0400274 var wg sync.WaitGroup
275 numConCurrentDeviceAgents := 20
276 for i := 0; i < numConCurrentDeviceAgents; i++ {
277 wg.Add(1)
278 a := da.createDeviceAgent(t)
279 go da.updateDeviceConcurrently(t, a, &wg)
280 }
281
282 wg.Wait()
khenaidoo6e55d9e2019-12-12 18:26:26 -0500283 }
khenaidoo6e55d9e2019-12-12 18:26:26 -0500284}
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700285func TestFlowUpdates(t *testing.T) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000286 ctx := context.Background()
287 da := newDATest(ctx)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700288 assert.NotNil(t, da)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000289 defer da.stopAll(ctx)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700290
291 log.SetPackageLogLevel("github.com/opencord/voltha-go/rw_core/core", log.DebugLevel)
292 // Start the Core
Rohan Agrawal31f21802020-06-12 05:38:46 +0000293 da.startCore(ctx)
294 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 -0700295
296 a := da.createDeviceAgent(t)
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400297 err1 := a.requestQueue.WaitForGreenLight(ctx)
298 assert.Nil(t, err1)
299 cloned := a.cloneDeviceWithoutLock()
300 cloned.AdminState, cloned.ConnectStatus, cloned.OperStatus = voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE
301 err2 := a.updateDeviceAndReleaseLock(ctx, cloned)
302 assert.Nil(t, err2)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700303 da.testFlowAddDeletes(t, a)
304}
305
306func TestGroupUpdates(t *testing.T) {
Rohan Agrawal31f21802020-06-12 05:38:46 +0000307 ctx := context.Background()
308 da := newDATest(ctx)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700309 assert.NotNil(t, da)
Rohan Agrawal31f21802020-06-12 05:38:46 +0000310 defer da.stopAll(ctx)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700311
312 // Start the Core
Rohan Agrawal31f21802020-06-12 05:38:46 +0000313 da.startCore(ctx)
314 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 -0700315 a := da.createDeviceAgent(t)
Kent Hagermanf6db9f12020-07-22 17:16:19 -0400316 err1 := a.requestQueue.WaitForGreenLight(ctx)
317 assert.Nil(t, err1)
318 cloned := a.cloneDeviceWithoutLock()
319 cloned.AdminState, cloned.ConnectStatus, cloned.OperStatus = voltha.AdminState_ENABLED, voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE
320 err2 := a.updateDeviceAndReleaseLock(ctx, cloned)
321 assert.Nil(t, err2)
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700322 da.testGroupAddDeletes(t, a)
323}
khenaidoob2121e52019-12-16 17:17:22 -0500324
325func isFlowSliceEqual(a, b []*ofp.OfpFlowStats) bool {
326 if len(a) != len(b) {
327 return false
328 }
329 sort.Slice(a, func(i, j int) bool {
330 return a[i].Id < a[j].Id
331 })
332 sort.Slice(b, func(i, j int) bool {
333 return b[i].Id < b[j].Id
334 })
335 for idx := range a {
336 if !proto.Equal(a[idx], b[idx]) {
337 return false
338 }
339 }
340 return true
341}
342
343func isGroupSliceEqual(a, b []*ofp.OfpGroupEntry) bool {
344 if len(a) != len(b) {
345 return false
346 }
347 sort.Slice(a, func(i, j int) bool {
348 return a[i].Desc.GroupId < a[j].Desc.GroupId
349 })
350 sort.Slice(b, func(i, j int) bool {
351 return b[i].Desc.GroupId < b[j].Desc.GroupId
352 })
353 for idx := range a {
354 if !proto.Equal(a[idx], b[idx]) {
355 return false
356 }
357 }
358 return true
359}
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700360func changeToFlowList(flowList map[uint64]*ofp.OfpFlowStats) []*ofp.OfpFlowStats {
361 flows := make([]*ofp.OfpFlowStats, 0)
362 for _, flow := range flowList {
363 flows = append(flows, flow)
364 }
365 return flows
khenaidoob2121e52019-12-16 17:17:22 -0500366}
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700367func changeToGroupList(groupList map[uint32]*ofp.OfpGroupEntry) []*ofp.OfpGroupEntry {
368 groups := make([]*ofp.OfpGroupEntry, 0)
369 for _, group := range groupList {
370 groups = append(groups, group)
371 }
372 return groups
373}
374func (dat *DATest) testFlowAddDeletes(t *testing.T, da *Agent) {
375 //Add new Flows on empty list
khenaidoob2121e52019-12-16 17:17:22 -0500376 newFlows := []*ofp.OfpFlowStats{
377 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
378 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
379 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
380 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700381 err := da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
382 assert.Nil(t, err)
383 daFlows := changeToFlowList(da.listDeviceFlows())
384 assert.True(t, isFlowSliceEqual(newFlows, daFlows))
khenaidoob2121e52019-12-16 17:17:22 -0500385
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700386 //Add new Flows on existing ones
387 newFlows = []*ofp.OfpFlowStats{
388 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500389 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270000, PacketCount: 0},
390 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700391
392 expectedFlows := []*ofp.OfpFlowStats{
393 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
394 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
395 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
396 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
397 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270000, PacketCount: 0},
398 }
399
400 err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
401 assert.Nil(t, err)
402 daFlows = changeToFlowList(da.listDeviceFlows())
403 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
404
405 //Add existing Flows again with a new flow
406 newFlows = []*ofp.OfpFlowStats{
407 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
408 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
409 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
410 }
411
412 expectedFlows = []*ofp.OfpFlowStats{
413 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
414 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
415 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
416 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
417 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
418 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
419 }
420
421 err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
422 assert.Nil(t, err)
423 daFlows = changeToFlowList(da.listDeviceFlows())
424 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
425
426 //Add already existing flows again
427 newFlows = []*ofp.OfpFlowStats{
428 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
429 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
430 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
431 }
432
433 expectedFlows = []*ofp.OfpFlowStats{
434 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
435 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
436 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
437 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
438 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
439 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
440 }
441
442 err = da.addFlowsAndGroups(context.Background(), newFlows, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
443 assert.Nil(t, err)
444 daFlows = changeToFlowList(da.listDeviceFlows())
445 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
446
447 //Delete flows
448 flowsToDelete := []*ofp.OfpFlowStats{
449 {Id: 126, TableId: 1260, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1260000, PacketCount: 0},
450 {Id: 127, TableId: 1270, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1270001, PacketCount: 0},
451 {Id: 128, TableId: 1280, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1280000, PacketCount: 0},
452 }
453
454 expectedFlows = []*ofp.OfpFlowStats{
khenaidoob2121e52019-12-16 17:17:22 -0500455 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
456 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
457 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
458 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700459
460 err = da.deleteFlowsAndGroups(context.Background(), flowsToDelete, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
461 assert.Nil(t, err)
462 daFlows = changeToFlowList(da.listDeviceFlows())
463 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
464 //Delete flows with an unexisting one
465 flowsToDelete = []*ofp.OfpFlowStats{
khenaidoob2121e52019-12-16 17:17:22 -0500466 {Id: 125, TableId: 1250, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1250000, PacketCount: 0},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700467 {Id: 129, TableId: 1290, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1290000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500468 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700469
470 expectedFlows = []*ofp.OfpFlowStats{
471 {Id: 123, TableId: 1230, Priority: 100, IdleTimeout: 0, Flags: 0, Cookie: 1230000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500472 {Id: 124, TableId: 1240, Priority: 1000, IdleTimeout: 0, Flags: 0, Cookie: 1240000, PacketCount: 0},
khenaidoob2121e52019-12-16 17:17:22 -0500473 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700474
475 err = da.deleteFlowsAndGroups(context.Background(), flowsToDelete, []*ofp.OfpGroupEntry{}, &voltha.FlowMetadata{})
476 assert.Nil(t, err)
477 daFlows = changeToFlowList(da.listDeviceFlows())
478 assert.True(t, isFlowSliceEqual(expectedFlows, daFlows))
khenaidoob2121e52019-12-16 17:17:22 -0500479}
480
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700481func (dat *DATest) testGroupAddDeletes(t *testing.T, da *Agent) {
482 //Add new Groups on empty list
khenaidoob2121e52019-12-16 17:17:22 -0500483 newGroups := []*ofp.OfpGroupEntry{
484 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
485 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
486 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700487 err := da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
488 assert.Nil(t, err)
489 daGroups := changeToGroupList(da.listDeviceGroups())
490 assert.True(t, isGroupSliceEqual(newGroups, daGroups))
khenaidoob2121e52019-12-16 17:17:22 -0500491
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700492 //Add new Groups on existing ones
493 newGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500494 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
495 {Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, Buckets: nil}},
496 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700497 expectedGroups := []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500498 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
499 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
500 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
501 {Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, Buckets: nil}},
502 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700503 err = da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
504 assert.Nil(t, err)
505 daGroups = changeToGroupList(da.listDeviceGroups())
506 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
khenaidoob2121e52019-12-16 17:17:22 -0500507
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700508 //Add new Groups on existing ones
509 newGroups = []*ofp.OfpGroupEntry{
510 {Desc: &ofp.OfpGroupDesc{Type: 3, 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 expectedGroups = []*ofp.OfpGroupEntry{
515 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500516 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
517 {Desc: &ofp.OfpGroupDesc{Type: 3, GroupId: 30, Buckets: nil}},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700518 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
519 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500520 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700521 err = da.addFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, newGroups, &voltha.FlowMetadata{})
522 assert.Nil(t, err)
523 daGroups = changeToGroupList(da.listDeviceGroups())
524 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
525
526 //Modify Group
527 updtGroups := []*ofp.OfpGroupEntry{
528 {Desc: &ofp.OfpGroupDesc{Type: 33, GroupId: 30, Buckets: nil}},
529 }
530 expectedGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500531 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500532 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700533 {Desc: &ofp.OfpGroupDesc{Type: 33, GroupId: 30, Buckets: nil}},
534 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
535 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
khenaidoob2121e52019-12-16 17:17:22 -0500536 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700537 err = da.updateFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, updtGroups, &voltha.FlowMetadata{})
538 assert.Nil(t, err)
539 daGroups = changeToGroupList(da.listDeviceGroups())
540 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
541
542 //Delete Group
543 delGroups := []*ofp.OfpGroupEntry{
544 {Desc: &ofp.OfpGroupDesc{Type: 33, GroupId: 30, Buckets: nil}},
545 }
546 expectedGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500547 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700548 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
549 {Desc: &ofp.OfpGroupDesc{Type: 44, GroupId: 40, Buckets: nil}},
550 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
551 }
552 err = da.deleteFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, delGroups, &voltha.FlowMetadata{})
553 assert.Nil(t, err)
554 daGroups = changeToGroupList(da.listDeviceGroups())
555 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
556
557 //Delete Group
558 delGroups = []*ofp.OfpGroupEntry{
khenaidoob2121e52019-12-16 17:17:22 -0500559 {Desc: &ofp.OfpGroupDesc{Type: 4, GroupId: 40, Buckets: nil}},
560 }
Mahir Gunyel03de0d32020-06-03 01:36:59 -0700561 expectedGroups = []*ofp.OfpGroupEntry{
562 {Desc: &ofp.OfpGroupDesc{Type: 1, GroupId: 10, Buckets: nil}},
563 {Desc: &ofp.OfpGroupDesc{Type: 2, GroupId: 20, Buckets: nil}},
564 {Desc: &ofp.OfpGroupDesc{Type: 5, GroupId: 50, Buckets: nil}},
565 }
566 err = da.deleteFlowsAndGroups(context.Background(), []*ofp.OfpFlowStats{}, delGroups, &voltha.FlowMetadata{})
567 assert.Nil(t, err)
568 daGroups = changeToGroupList(da.listDeviceGroups())
569 assert.True(t, isGroupSliceEqual(expectedGroups, daGroups))
khenaidoob2121e52019-12-16 17:17:22 -0500570}