blob: 7a1079d07368d15e7940e8b562ab1237adc7b33c [file] [log] [blame]
khenaidoo0458db62019-06-20 08:50:36 -04001// +build integration
2
3/*
4 * Copyright 2018-present Open Networking Foundation
5
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9
10 * http://www.apache.org/licenses/LICENSE-2.0
11
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18package core
19
20import (
21 "context"
22 "fmt"
23 "github.com/google/uuid"
khenaidoo0458db62019-06-20 08:50:36 -040024 fu "github.com/opencord/voltha-go/rw_core/utils"
25 tu "github.com/opencord/voltha-go/tests/utils"
serkant.uluderya2ae470f2020-01-21 11:13:09 -080026 "github.com/opencord/voltha-lib-go/v3/pkg/log"
27 "github.com/opencord/voltha-protos/v3/go/common"
28 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
29 "github.com/opencord/voltha-protos/v3/go/voltha"
khenaidoo0458db62019-06-20 08:50:36 -040030 "github.com/stretchr/testify/assert"
31 "google.golang.org/grpc/metadata"
32 "math"
33 "os"
Manikkaraj kb1a10922019-07-29 12:10:34 -040034 "reflect"
35 "sync"
khenaidoo0458db62019-06-20 08:50:36 -040036 "testing"
37 "time"
38)
39
40var stub voltha.VolthaServiceClient
41var volthaSerialNumberKey string
Manikkaraj kb1a10922019-07-29 12:10:34 -040042var mutex sync.Mutex
khenaidoo0458db62019-06-20 08:50:36 -040043
44/*
45 This local "integration" test uses one RW-Core, one simulated_olt and one simulated_onu adapter to test flows
46(add/delete), in a development environment. It uses docker-compose to set up the local environment. However, it can
47easily be extended to run in k8s environment.
48
49The compose files used are located under %GOPATH/src/github.com/opencord/voltha-go/compose. If the GOPATH is not set
50then you can specify the location of the compose files by using COMPOSE_PATH to set the compose files location.
51
52To run this test: DOCKER_HOST_IP=<local IP> go test -v
53
54NOTE: Since this is an integration test that involves several containers and features (device creation, device
55activation, validation of parent and discovered devices, validation of logical device as well as add/delete flows)
56then a failure can occur anywhere not just when testing flows.
57
58*/
59
60var allDevices map[string]*voltha.Device
61var allLogicalDevices map[string]*voltha.LogicalDevice
62
63var composePath string
64
65const (
Manikkaraj kb1a10922019-07-29 12:10:34 -040066 GrpcPort = 50057
67 NumOfOLTs = 1
68 NumOfONUsPerOLT = 4 // This should coincide with the number of onus per olt in adapters-simulated.yml file
69 MeterIDStart = 1
70 MeterIDStop = 1000
khenaidoo0458db62019-06-20 08:50:36 -040071)
72
73func setup() {
khenaidoo0458db62019-06-20 08:50:36 -040074 volthaSerialNumberKey = "voltha_serial_number"
75 allDevices = make(map[string]*voltha.Device)
76 allLogicalDevices = make(map[string]*voltha.LogicalDevice)
77
78 grpcHostIP := os.Getenv("DOCKER_HOST_IP")
79 goPath := os.Getenv("GOPATH")
80 if goPath != "" {
81 composePath = fmt.Sprintf("%s/src/github.com/opencord/voltha-go/compose", goPath)
82 } else {
83 composePath = os.Getenv("COMPOSE_PATH")
84 }
85
86 fmt.Println("Using compose path:", composePath)
87
88 //Start the simulated environment
89 if err = tu.StartSimulatedEnv(composePath); err != nil {
90 fmt.Println("Failure starting simulated environment:", err)
91 os.Exit(10)
92 }
93
Manikkaraj kb1a10922019-07-29 12:10:34 -040094 stub, err = tu.SetupGrpcConnectionToCore(grpcHostIP, GrpcPort)
khenaidoo0458db62019-06-20 08:50:36 -040095 if err != nil {
96 fmt.Println("Failure connecting to Voltha Core:", err)
97 os.Exit(11)
98 }
99
100 // Wait for the simulated devices to be registered in the Voltha Core
101 adapters := []string{"simulated_olt", "simulated_onu"}
102 if _, err = tu.WaitForAdapterRegistration(stub, adapters, 20); err != nil {
103 fmt.Println("Failure retrieving adapters:", err)
104 os.Exit(12)
105 }
106}
107
108func shutdown() {
109 err := tu.StopSimulatedEnv(composePath)
110 if err != nil {
111 fmt.Println("Failure stop simulated environment:", err)
112 }
113}
114
115func refreshLocalDeviceCache(stub voltha.VolthaServiceClient) error {
116 retrievedDevices, err := tu.ListDevices(stub)
117 if err != nil {
118 return err
119 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400120 mutex.Lock()
khenaidoo0458db62019-06-20 08:50:36 -0400121 for _, d := range retrievedDevices.Items {
122 allDevices[d.Id] = d
123 }
khenaidoo0458db62019-06-20 08:50:36 -0400124 retrievedLogicalDevices, err := tu.ListLogicalDevices(stub)
125 if err != nil {
126 return err
127 }
128
129 for _, ld := range retrievedLogicalDevices.Items {
130 allLogicalDevices[ld.Id] = ld
131 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400132 mutex.Unlock()
khenaidoo0458db62019-06-20 08:50:36 -0400133 return nil
134}
135
136func makeSimpleFlowMod(fa *fu.FlowArgs) *ofp.OfpFlowMod {
137 matchFields := make([]*ofp.OfpOxmField, 0)
138 for _, val := range fa.MatchFields {
139 matchFields = append(matchFields, &ofp.OfpOxmField{Field: &ofp.OfpOxmField_OfbField{OfbField: val}})
140 }
141 return fu.MkSimpleFlowMod(matchFields, fa.Actions, fa.Command, fa.KV)
142}
143
Manikkaraj kb1a10922019-07-29 12:10:34 -0400144func addEAPOLFlow(stub voltha.VolthaServiceClient, ld *voltha.LogicalDevice, port *voltha.LogicalPort, meterID uint64,
145 ch chan interface{}) {
khenaidoo0458db62019-06-20 08:50:36 -0400146 var fa *fu.FlowArgs
147 fa = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400148 KV: fu.OfpFlowModArgs{"priority": 2000, "meter_id": meterID},
khenaidoo0458db62019-06-20 08:50:36 -0400149 MatchFields: []*ofp.OfpOxmOfbField{
150 fu.InPort(port.OfpPort.PortNo),
151 fu.EthType(0x888e),
152 },
153 Actions: []*ofp.OfpAction{
154 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
155 },
156 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400157 // Don't add meterID 0
158 if meterID == 0 {
159 delete(fa.KV, "meter_id")
160 }
161
khenaidoo0458db62019-06-20 08:50:36 -0400162 matchFields := make([]*ofp.OfpOxmField, 0)
163 for _, val := range fa.MatchFields {
164 matchFields = append(matchFields, &ofp.OfpOxmField{Field: &ofp.OfpOxmField_OfbField{OfbField: val}})
165 }
166 f := ofp.FlowTableUpdate{FlowMod: makeSimpleFlowMod(fa), Id: ld.Id}
167
168 ui := uuid.New()
169 ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
170 if response, err := stub.UpdateLogicalDeviceFlowTable(ctx, &f); err != nil {
171 ch <- err
172 } else {
173 ch <- response
174 }
175}
176
177func getNumUniPort(ld *voltha.LogicalDevice, lPortNos ...uint32) int {
178 num := 0
179 if len(lPortNos) > 0 {
180 for _, pNo := range lPortNos {
181 for _, lPort := range ld.Ports {
182 if !lPort.RootPort && lPort.OfpPort.PortNo == pNo {
183 num += 1
184 }
185 }
186 }
187 } else {
188 for _, port := range ld.Ports {
189 if !port.RootPort {
190 num += 1
191 }
192 }
193 }
194 return num
195}
196
197func filterOutPort(lPort *voltha.LogicalPort, lPortNos ...uint32) bool {
198 if len(lPortNos) == 0 {
199 return false
200 }
201 for _, pNo := range lPortNos {
202 if lPort.OfpPort.PortNo == pNo {
203 return false
204 }
205 }
206 return true
207}
208
Manikkaraj kb1a10922019-07-29 12:10:34 -0400209func verifyEAPOLFlows(t *testing.T, ld *voltha.LogicalDevice, meterID uint64, lPortNos ...uint32) {
khenaidoo0458db62019-06-20 08:50:36 -0400210 // First get the flows from the logical device
Manikkaraj kb1a10922019-07-29 12:10:34 -0400211 fmt.Println("Info: verifying EAPOL flows")
khenaidoo0458db62019-06-20 08:50:36 -0400212 lFlows := ld.Flows
213 assert.Equal(t, getNumUniPort(ld, lPortNos...), len(lFlows.Items))
214
215 onuDeviceId := ""
216
217 // Verify that the flows in the logical device is what was pushed
218 for _, lPort := range ld.Ports {
219 if lPort.RootPort {
220 continue
221 }
222 if filterOutPort(lPort, lPortNos...) {
223 continue
224 }
225 onuDeviceId = lPort.DeviceId
226 var fa *fu.FlowArgs
227 fa = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400228 KV: fu.OfpFlowModArgs{"priority": 2000, "meter_id": meterID},
khenaidoo0458db62019-06-20 08:50:36 -0400229 MatchFields: []*ofp.OfpOxmOfbField{
230 fu.InPort(lPort.OfpPort.PortNo),
231 fu.EthType(0x888e),
232 },
233 Actions: []*ofp.OfpAction{
234 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
235 },
236 }
Manikkaraj kb1a10922019-07-29 12:10:34 -0400237 if meterID == 0 {
238 delete(fa.KV, "meter_id")
239 }
khenaidoo0458db62019-06-20 08:50:36 -0400240 expectedLdFlow := fu.MkFlowStat(fa)
241 assert.Equal(t, true, tu.IsFlowPresent(expectedLdFlow, lFlows.Items))
242 }
243
244 // Verify the OLT flows
245 retrievedOltFlows := allDevices[ld.RootDeviceId].Flows.Items
Manikkaraj kb1a10922019-07-29 12:10:34 -0400246 assert.Equal(t, NumOfOLTs*getNumUniPort(ld, lPortNos...)*1, len(retrievedOltFlows))
khenaidoo0458db62019-06-20 08:50:36 -0400247 for _, lPort := range ld.Ports {
248 if lPort.RootPort {
249 continue
250 }
251 if filterOutPort(lPort, lPortNos...) {
252 continue
253 }
254
255 fa := &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400256 KV: fu.OfpFlowModArgs{"priority": 2000, "meter_id": meterID},
khenaidoo0458db62019-06-20 08:50:36 -0400257 MatchFields: []*ofp.OfpOxmOfbField{
258 fu.InPort(1),
khenaidoo0458db62019-06-20 08:50:36 -0400259 fu.TunnelId(uint64(lPort.OfpPort.PortNo)),
260 fu.EthType(0x888e),
261 },
262 Actions: []*ofp.OfpAction{
263 fu.PushVlan(0x8100),
264 fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000)),
265 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
266 },
267 }
268 expectedOltFlow := fu.MkFlowStat(fa)
269 assert.Equal(t, true, tu.IsFlowPresent(expectedOltFlow, retrievedOltFlows))
khenaidoo0458db62019-06-20 08:50:36 -0400270 }
271 // Verify the ONU flows
272 retrievedOnuFlows := allDevices[onuDeviceId].Flows.Items
273 assert.Equal(t, 0, len(retrievedOnuFlows))
274}
275
276func verifyNOFlows(t *testing.T, ld *voltha.LogicalDevice, lPortNos ...uint32) {
277 if len(lPortNos) == 0 {
278 assert.Equal(t, 0, len(ld.Flows.Items))
279 for _, d := range allDevices {
280 if d.ParentId == ld.Id {
281 assert.Equal(t, 0, len(d.Flows.Items))
282 }
283 }
284 return
285 }
286 for _, p := range lPortNos {
287 // Check absence of flows in logical device for that port
288 for _, f := range ld.Flows.Items {
289 assert.NotEqual(t, p, fu.GetInPort(f))
290 }
291 // Check absence of flows in the parent device for that port
292 for _, d := range allDevices {
293 if d.ParentId == ld.Id {
294 for _, f := range d.Flows.Items {
295 assert.NotEqual(t, p, fu.GetTunnelId(f))
296 }
297 }
298 }
299 // TODO: check flows in child device. Not required for the use cases being tested
300 }
301
302}
303
Manikkaraj kb1a10922019-07-29 12:10:34 -0400304func installEapolFlows(stub voltha.VolthaServiceClient, lDevice *voltha.LogicalDevice, meterID uint64, lPortNos ...uint32) error {
khenaidoo0458db62019-06-20 08:50:36 -0400305 requestNum := 0
306 combineCh := make(chan interface{})
307 if len(lPortNos) > 0 {
308 fmt.Println("Installing EAPOL flows on ports:", lPortNos)
309 for _, p := range lPortNos {
310 for _, lport := range lDevice.Ports {
311 if !lport.RootPort && lport.OfpPort.PortNo == p {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400312 go addEAPOLFlow(stub, lDevice, lport, meterID, combineCh)
khenaidoo0458db62019-06-20 08:50:36 -0400313 requestNum += 1
314 }
315 }
316 }
317 } else {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400318 fmt.Println("Installing EAPOL flows on logical device", lDevice.Id)
khenaidoo0458db62019-06-20 08:50:36 -0400319 for _, lport := range lDevice.Ports {
320 if !lport.RootPort {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400321 go addEAPOLFlow(stub, lDevice, lport, meterID, combineCh)
khenaidoo0458db62019-06-20 08:50:36 -0400322 requestNum += 1
323 }
324 }
khenaidoo0458db62019-06-20 08:50:36 -0400325 }
326 receivedResponse := 0
327 var err error
328 for {
329 select {
330 case res, ok := <-combineCh:
331 receivedResponse += 1
332 if !ok {
333 } else if er, ok := res.(error); ok {
334 err = er
335 }
336 }
337 if receivedResponse == requestNum {
338 break
339 }
340 }
341 return err
342}
343
344func deleteAllFlows(stub voltha.VolthaServiceClient, lDevice *voltha.LogicalDevice) error {
345 fmt.Println("Deleting all flows for logical device:", lDevice.Id)
346 ui := uuid.New()
347 ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
348 ch := make(chan interface{})
349 defer close(ch)
350 fa := &fu.FlowArgs{
351 KV: fu.OfpFlowModArgs{"table_id": uint64(ofp.OfpTable_OFPTT_ALL),
352 "cookie_mask": 0,
353 "out_port": uint64(ofp.OfpPortNo_OFPP_ANY),
354 "out_group": uint64(ofp.OfpGroup_OFPG_ANY),
355 },
356 }
357 cmd := ofp.OfpFlowModCommand_OFPFC_DELETE
358 fa.Command = &cmd
359 flowMod := fu.MkSimpleFlowMod(fu.ToOfpOxmField(fa.MatchFields), fa.Actions, fa.Command, fa.KV)
360 f := ofp.FlowTableUpdate{FlowMod: flowMod, Id: lDevice.Id}
361 _, err := stub.UpdateLogicalDeviceFlowTable(ctx, &f)
362 return err
363}
364
Manikkaraj kb1a10922019-07-29 12:10:34 -0400365func deleteEapolFlow(stub voltha.VolthaServiceClient, lDevice *voltha.LogicalDevice, meterID uint64, lPortNo uint32) error {
khenaidoo0458db62019-06-20 08:50:36 -0400366 fmt.Println("Deleting flows from port ", lPortNo, " of logical device ", lDevice.Id)
367 ui := uuid.New()
368 var fa *fu.FlowArgs
369 ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(volthaSerialNumberKey, ui.String()))
370 fa = &fu.FlowArgs{
Manikkaraj kb1a10922019-07-29 12:10:34 -0400371 KV: fu.OfpFlowModArgs{"priority": 2000, "meter_id": meterID},
khenaidoo0458db62019-06-20 08:50:36 -0400372 MatchFields: []*ofp.OfpOxmOfbField{
373 fu.InPort(lPortNo),
374 fu.EthType(0x888e),
375 },
376 Actions: []*ofp.OfpAction{
377 fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
378 },
379 }
380 matchFields := make([]*ofp.OfpOxmField, 0)
381 for _, val := range fa.MatchFields {
382 matchFields = append(matchFields, &ofp.OfpOxmField{Field: &ofp.OfpOxmField_OfbField{OfbField: val}})
383 }
384 cmd := ofp.OfpFlowModCommand_OFPFC_DELETE
385 fa.Command = &cmd
386 f := ofp.FlowTableUpdate{FlowMod: makeSimpleFlowMod(fa), Id: lDevice.Id}
387 _, err := stub.UpdateLogicalDeviceFlowTable(ctx, &f)
388 return err
389}
390
Manikkaraj kb1a10922019-07-29 12:10:34 -0400391func runInstallEapolFlows(t *testing.T, stub voltha.VolthaServiceClient, meterID uint64, lPortNos ...uint32) {
khenaidoo0458db62019-06-20 08:50:36 -0400392 err := refreshLocalDeviceCache(stub)
393 assert.Nil(t, err)
394
395 for _, ld := range allLogicalDevices {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400396 err = installEapolFlows(stub, ld, meterID, lPortNos...)
khenaidoo0458db62019-06-20 08:50:36 -0400397 assert.Nil(t, err)
398 }
399
400 err = refreshLocalDeviceCache(stub)
401 assert.Nil(t, err)
khenaidoo0458db62019-06-20 08:50:36 -0400402 for _, ld := range allLogicalDevices {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400403 verifyEAPOLFlows(t, ld, meterID, lPortNos...)
khenaidoo0458db62019-06-20 08:50:36 -0400404 }
405}
406
407func runDeleteAllFlows(t *testing.T, stub voltha.VolthaServiceClient) {
408 fmt.Println("Removing ALL flows ...")
409 err := refreshLocalDeviceCache(stub)
410 assert.Nil(t, err)
411
412 for _, ld := range allLogicalDevices {
413 err = deleteAllFlows(stub, ld)
414 assert.Nil(t, err)
415 }
416
417 err = refreshLocalDeviceCache(stub)
418 assert.Nil(t, err)
419
420 for _, ld := range allLogicalDevices {
421 verifyNOFlows(t, ld)
422 }
423}
424
Manikkaraj kb1a10922019-07-29 12:10:34 -0400425func runDeleteEapolFlows(t *testing.T, stub voltha.VolthaServiceClient, ld *voltha.LogicalDevice, meterID uint64, lPortNos ...uint32) {
khenaidoo0458db62019-06-20 08:50:36 -0400426 err := refreshLocalDeviceCache(stub)
427 assert.Nil(t, err)
428
429 if len(lPortNos) == 0 {
430 err = deleteAllFlows(stub, ld)
431 assert.Nil(t, err)
432 } else {
433 for _, lPortNo := range lPortNos {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400434 err = deleteEapolFlow(stub, ld, meterID, lPortNo)
khenaidoo0458db62019-06-20 08:50:36 -0400435 assert.Nil(t, err)
436 }
437 }
438
439 err = refreshLocalDeviceCache(stub)
440 assert.Nil(t, err)
441
442 for _, lde := range allLogicalDevices {
443 if lde.Id == ld.Id {
444 verifyNOFlows(t, lde, lPortNos...)
445 break
446 }
447 }
448}
449
Manikkaraj kb1a10922019-07-29 12:10:34 -0400450func formulateMeterModUpdateRequest(command ofp.OfpMeterModCommand, meterType ofp.OfpMeterBandType, ldID string, rate,
451 burstSize uint32, meterID uint32) *ofp.MeterModUpdate {
452 meterModUpdateRequest := &ofp.MeterModUpdate{
453 Id: ldID,
454 MeterMod: &ofp.OfpMeterMod{
455 Command: command,
456 Flags: 0,
457 MeterId: meterID,
458 Bands: []*ofp.OfpMeterBandHeader{{
459 Type: meterType,
460 Rate: rate,
461 BurstSize: burstSize,
462 Data: nil,
463 }},
464 },
465 }
466 return meterModUpdateRequest
467}
468
469func formulateMeters(rate, burstsize, meterID uint32, flowCount uint32) *ofp.Meters {
470 // Formulate and return the applied meter band
471 ofpMeterBandHeaderSlice := []*ofp.OfpMeterBandHeader{{
472 Type: ofp.OfpMeterBandType_OFPMBT_EXPERIMENTER,
473 Rate: rate,
474 BurstSize: burstsize,
475 }}
476 BandStats := []*ofp.OfpMeterBandStats{{}}
477 appliedMeters_Meters := []*ofp.OfpMeterEntry{{
478 Config: &ofp.OfpMeterConfig{
479 Flags: 0,
480 MeterId: meterID,
481 Bands: ofpMeterBandHeaderSlice,
482 },
483 Stats: &ofp.OfpMeterStats{
484 MeterId: meterID,
485 BandStats: BandStats,
486 FlowCount: flowCount,
487 },
488 }}
489 appliedMeters := &ofp.Meters{
490 Items: appliedMeters_Meters,
491 }
492 return appliedMeters
493}
494
495func meterAdd(t *testing.T, meterID, rate, burstSize uint32) {
496 var err error
497 for _, logicalDevice := range allLogicalDevices {
498 meterModupdateRequest := formulateMeterModUpdateRequest(ofp.OfpMeterModCommand_OFPMC_ADD,
499 ofp.OfpMeterBandType_OFPMBT_EXPERIMENTER, logicalDevice.Id, rate, burstSize, meterID)
500 _, err = stub.UpdateLogicalDeviceMeterTable(context.Background(), meterModupdateRequest)
501 assert.Nil(t, err)
502 }
503}
504
505func meterMod(t *testing.T, meterID, rate, burstSize uint32) {
506 for _, logicalDevice := range allLogicalDevices {
507 meterModUpdateRequest := formulateMeterModUpdateRequest(ofp.OfpMeterModCommand_OFPMC_MODIFY,
508 ofp.OfpMeterBandType_OFPMBT_EXPERIMENTER, logicalDevice.Id, rate, burstSize, meterID)
509 _, err := stub.UpdateLogicalDeviceMeterTable(context.Background(), meterModUpdateRequest)
510 assert.Nil(t, err)
511 }
512}
513
514//MeterDel deletes a meter with given meter-ID
515func meterDel(t *testing.T, meterID uint32) {
516 for _, logicalDevice := range allLogicalDevices {
517 meterModUpdateRequest := formulateMeterModUpdateRequest(ofp.OfpMeterModCommand_OFPMC_DELETE,
518 ofp.OfpMeterBandType_OFPMBT_EXPERIMENTER, logicalDevice.Id, uint32(1600), uint32(1600), meterID)
519 _, err := stub.UpdateLogicalDeviceMeterTable(context.Background(), meterModUpdateRequest)
520 assert.Nil(t, err)
521 }
522}
523
524// WaitGroup passed to this function must not be nil
525func addMultipleMeterSequentially(t *testing.T, startMeterId, endMeterId, rate, burstSize uint32, wg *sync.WaitGroup) {
526 defer wg.Done()
527 for meterID := startMeterId; meterID <= endMeterId; meterID++ {
528 meterAdd(t, meterID, rate, burstSize)
529 }
530}
531
532func modMultipleMeterSequentially(t *testing.T, startMeterId, endMeterId, rate, burstSize uint32, wg *sync.WaitGroup) {
533 defer wg.Done()
534 for meterID := startMeterId; meterID <= endMeterId; meterID++ {
535 meterMod(t, meterID, rate, burstSize)
536 }
537}
538
539func delMultipleMeterSequential(t *testing.T, startMeterId, endMeterId uint32, wg *sync.WaitGroup) {
540 defer wg.Done()
541 for meterID := startMeterId; meterID <= endMeterId; meterID++ {
542 meterDel(t, meterID)
543 }
544}
545
546func verifyMeter(t *testing.T, meterID, rate, burstSize, flowCount uint32) {
547 expectedMeter := formulateOfpMeterEntry(meterID, flowCount, rate, burstSize)
548 isMeterPresent := false
549 for _, lD := range allLogicalDevices {
550 for _, meter := range lD.Meters.Items {
551 isMeterPresent = reflect.DeepEqual(meter, expectedMeter)
552 if isMeterPresent == true {
553 break
554 }
555 }
556 if isMeterPresent {
557 break
558 }
559 }
560 if !isMeterPresent {
561 fmt.Printf("Error : Expected %+v\n", expectedMeter)
562 }
563 assert.Equal(t, true, isMeterPresent)
564}
565
566func verifyNoMeters(t *testing.T) {
567 err := refreshLocalDeviceCache(stub)
568 assert.Nil(t, err)
569 expectedMeters := &ofp.Meters{}
570 for _, logicalDevice := range allLogicalDevices {
571 result := reflect.DeepEqual(logicalDevice.Meters, expectedMeters)
572 fmt.Println("Meter Present After Delete :--- ", logicalDevice.Meters)
573 assert.Equal(t, true, result)
574 }
575}
576
577func formulateOfpMeterEntry(meterID, flowCount, rate, burstSize uint32) *ofp.OfpMeterEntry {
578 value := &ofp.OfpMeterEntry{
579 Config: &ofp.OfpMeterConfig{
580 MeterId: meterID,
581 Bands: []*ofp.OfpMeterBandHeader{{
582 Type: ofp.OfpMeterBandType_OFPMBT_EXPERIMENTER,
583 Rate: rate,
584 BurstSize: burstSize,
585 }},
586 },
587 Stats: &ofp.OfpMeterStats{
588 MeterId: meterID,
589 FlowCount: flowCount,
590 BandStats: []*ofp.OfpMeterBandStats{{}},
591 },
592 }
593
594 return value
595}
596
597func deleteAllMeters(t *testing.T) {
598 err := refreshLocalDeviceCache(stub)
599 assert.Nil(t, err)
600 for _, lD := range allLogicalDevices {
601 for _, meter := range lD.Meters.Items {
602 meterDel(t, meter.Config.MeterId)
603 }
604 }
605}
606
607func installMultipleFlowsWithMeter(t *testing.T, startMeterId, stopMeterId uint64, wg *sync.WaitGroup) {
608 defer wg.Done()
609 err := refreshLocalDeviceCache(stub)
610 assert.Nil(t, err)
611
612 for meterID := startMeterId; meterID <= stopMeterId; meterID++ {
613 runInstallEapolFlows(t, stub, uint64(meterID), 100, 101)
614 }
615}
616
khenaidoo0458db62019-06-20 08:50:36 -0400617func createAndEnableDevices(t *testing.T) {
618 err := tu.SetAllLogLevel(stub, voltha.Logging{Level: common.LogLevel_WARNING})
619 assert.Nil(t, err)
620
621 err = tu.SetLogLevel(stub, voltha.Logging{Level: common.LogLevel_DEBUG, PackageName: "github.com/opencord/voltha-go/rw_core/core"})
622 assert.Nil(t, err)
623
624 startTime := time.Now()
625
626 //Pre-provision the parent device
627 oltDevice, err := tu.PreProvisionDevice(stub)
628 assert.Nil(t, err)
629
Manikkaraj kb1a10922019-07-29 12:10:34 -0400630 fmt.Println("Creation of ", NumOfOLTs, " OLT devices took:", time.Since(startTime))
khenaidoo0458db62019-06-20 08:50:36 -0400631
632 startTime = time.Now()
633
634 //Enable all parent device - this will enable the child devices as well as validate the child devices
Manikkaraj kb1a10922019-07-29 12:10:34 -0400635 err = tu.EnableDevice(stub, oltDevice, NumOfONUsPerOLT)
khenaidoo0458db62019-06-20 08:50:36 -0400636 assert.Nil(t, err)
637
638 fmt.Println("Enabling of OLT device took:", time.Since(startTime))
639
640 // Wait until the core and adapters sync up after an enabled
Manikkaraj kb1a10922019-07-29 12:10:34 -0400641 time.Sleep(time.Duration(math.Max(10, float64(NumOfOLTs*NumOfONUsPerOLT)/2)) * time.Second)
khenaidoo0458db62019-06-20 08:50:36 -0400642
Manikkaraj kb1a10922019-07-29 12:10:34 -0400643 err = tu.VerifyDevices(stub, NumOfONUsPerOLT)
khenaidoo0458db62019-06-20 08:50:36 -0400644 assert.Nil(t, err)
645
Manikkaraj kb1a10922019-07-29 12:10:34 -0400646 lds, err := tu.VerifyLogicalDevices(stub, oltDevice, NumOfONUsPerOLT)
khenaidoo0458db62019-06-20 08:50:36 -0400647 assert.Nil(t, err)
648 assert.Equal(t, 1, len(lds.Items))
649}
650
651func TestFlowManagement(t *testing.T) {
Manikkaraj kb1a10922019-07-29 12:10:34 -0400652 //1. Test creation and activation of the devices. This will validate the devices as well as the logical device created
khenaidoo0458db62019-06-20 08:50:36 -0400653 createAndEnableDevices(t)
654
655 //2. Test installation of EAPOL flows
Manikkaraj kb1a10922019-07-29 12:10:34 -0400656 runInstallEapolFlows(t, stub, 0)
khenaidoo0458db62019-06-20 08:50:36 -0400657
658 //3. Test deletion of all EAPOL flows
659 runDeleteAllFlows(t, stub)
660
661 //4. Test installation of EAPOL flows on specific ports
Manikkaraj kb1a10922019-07-29 12:10:34 -0400662 runInstallEapolFlows(t, stub, 0, 101, 102)
khenaidoo0458db62019-06-20 08:50:36 -0400663
664 lds, err := tu.ListLogicalDevices(stub)
665 assert.Nil(t, err)
666
667 //5. Test deletion of EAPOL on a specific port for a given logical device
Manikkaraj kb1a10922019-07-29 12:10:34 -0400668 runDeleteEapolFlows(t, stub, lds.Items[0], 0, 101)
669}
670
671// Meter Add Test
672func TestMeters(t *testing.T) {
673 //1. Start test for meter add
674 meterAdd(t, 1, 1600, 1600)
675 err := refreshLocalDeviceCache(stub)
676 assert.Nil(t, err)
677 verifyMeter(t, 1, 1600, 1600, 0)
678
679 //2. Start test for meter mod
680 meterMod(t, 1, 6400, 6400)
681 err = refreshLocalDeviceCache(stub)
682 assert.Nil(t, err)
683 verifyMeter(t, 1, 6400, 6400, 0)
684
685 //3. Start test for meter del
686 meterDel(t, 1)
687 err = refreshLocalDeviceCache(stub)
688 assert.Nil(t, err)
689 verifyNoMeters(t)
690}
691
692func TestFlowManagementWithMeters(t *testing.T) {
693 //1. Delete existing flows
694 for _, logicaldevice := range allLogicalDevices {
695 err := deleteAllFlows(stub, logicaldevice)
696 assert.Nil(t, err)
697 }
698 deleteAllMeters(t)
699 //2. Refresh the local cache so that the changes are reflected here
700 err := refreshLocalDeviceCache(stub)
701 assert.Nil(t, err)
702
703 //3. Add meter with ID
704 meterAdd(t, 1, 1600, 1600)
705
706 err = refreshLocalDeviceCache(stub)
707 assert.Nil(t, err)
708
709 //4. Verify that the meter is installed
710 verifyMeter(t, 1, 1600, 1600, 0)
711
712 //3. Test installation of EAPOL flows with meter (Add and verify the flow)
713 runInstallEapolFlows(t, stub, MeterIDStart)
714
715 //4. Test deletion of all EAPOL flows
716 runDeleteAllFlows(t, stub)
717
718 //5. Test installation of EAPOL flows on specific ports with meter (Add and verify the flows)
719 runInstallEapolFlows(t, stub, MeterIDStart, 101, 102)
720
721 lds, err := tu.ListLogicalDevices(stub)
722 assert.Nil(t, err)
723
724 //6. Test deletion of EAPOL on a specific port for a given logical device
725 runDeleteEapolFlows(t, stub, lds.Items[0], MeterIDStart, 101)
726}
727
728func TestMultipleMeterAddSequential(t *testing.T) {
729 //1. Delete existing flows
730 for _, logicaldevice := range allLogicalDevices {
731 err := deleteAllFlows(stub, logicaldevice)
732 assert.Nil(t, err)
733 }
734
735 // Delete All The Previously Installed Meters
736 deleteAllMeters(t)
737 // Verify that no meters are present
738 err := refreshLocalDeviceCache(stub)
739 assert.Nil(t, err)
740 verifyNoMeters(t)
741 //2. Add Meter Sequentially
742 // Here wait-group is not required, creating and passing wait-group only because the function addMultipleMeterSequentially
743 // expects wait group.
744 var wg sync.WaitGroup
745 wg.Add(1)
746 addMultipleMeterSequentially(t, MeterIDStart, MeterIDStop, 1600, 1600, &wg)
747
748 err = refreshLocalDeviceCache(stub)
749 assert.Nil(t, err)
750
751 //3. Verify that the meters are installed
752 for meterID := MeterIDStart; meterID <= MeterIDStop; meterID++ {
753 verifyMeter(t, uint32(meterID), 1600, 1600, 0)
754 }
755}
756
757func TestMeterDeleteParallel(t *testing.T) {
758 var wg sync.WaitGroup
759 wg.Add(4)
760 go delMultipleMeterSequential(t, MeterIDStart, MeterIDStop/4, &wg)
761 go delMultipleMeterSequential(t, MeterIDStop/4+1, (MeterIDStop / 2), &wg)
762 go delMultipleMeterSequential(t, (MeterIDStop/2)+1, MeterIDStop/4*3, &wg)
763 go delMultipleMeterSequential(t, (MeterIDStop/4*3)+1, MeterIDStop, &wg)
764 wg.Wait()
765
766 verifyNoMeters(t)
767}
768
769func TestMultipleMeterAddParallel(t *testing.T) {
770 err := refreshLocalDeviceCache(stub)
771 assert.Nil(t, err)
772
773 for _, logicaldevice := range allLogicalDevices {
774 err := deleteAllFlows(stub, logicaldevice)
775 assert.Nil(t, err)
776 }
777
778 var wg sync.WaitGroup
779 wg.Add(4)
780 go addMultipleMeterSequentially(t, MeterIDStart, (MeterIDStop / 4), 3200, 3200, &wg)
781 go addMultipleMeterSequentially(t, (MeterIDStop/4 + 1), MeterIDStop/2, 3200, 3200, &wg)
782 go addMultipleMeterSequentially(t, MeterIDStop/2+1, (MeterIDStop / 4 * 3), 3200, 3200, &wg)
783 go addMultipleMeterSequentially(t, (MeterIDStop/4*3)+1, MeterIDStop, 3200, 3200, &wg)
784
785 wg.Wait()
786
787 // Verify the devices
788 err = tu.VerifyDevices(stub, NumOfONUsPerOLT)
789 assert.Nil(t, err)
790
791 err = refreshLocalDeviceCache(stub)
792 assert.Nil(t, err)
793 for meterID := MeterIDStart; meterID <= MeterIDStop; meterID++ {
794 fmt.Println("Verifying meter ID :", meterID)
795 verifyMeter(t, uint32(meterID), 3200, 3200, 0)
796 }
797}
798
799func TestMultipleMeterModSequential(t *testing.T) {
800 var wg sync.WaitGroup
801 wg.Add(1)
802 //1. Modify all the existing meters
803 modMultipleMeterSequentially(t, MeterIDStart, MeterIDStop, 6400, 6400, &wg)
804 //2. Verify that the device state is proper after updating so many meters
805 err := tu.VerifyDevices(stub, NumOfONUsPerOLT)
806 assert.Nil(t, err)
807
808 //3. Refresh logical device cache
809 err = refreshLocalDeviceCache(stub)
810 assert.Nil(t, err)
811
812 //4. Verify that all the meters got modified
813 for meterID := MeterIDStart; meterID <= MeterIDStop; meterID++ {
814 fmt.Println("Verifying meter ID :", meterID)
815 verifyMeter(t, uint32(meterID), 6400, 6400, 0)
816 }
817}
818
819func TestMultipleMeterModParallel(t *testing.T) {
820 var wg sync.WaitGroup
821 wg.Add(4)
822 //1. Modify all the existing meters
823 go modMultipleMeterSequentially(t, MeterIDStart, MeterIDStop/4, 1600, 1600, &wg)
824 go modMultipleMeterSequentially(t, (MeterIDStop/4 + 1), MeterIDStop/2, 1600, 1600, &wg)
825 go modMultipleMeterSequentially(t, (MeterIDStop/2 + 1), (MeterIDStop / 4 * 3), 1600, 1600, &wg)
826 go modMultipleMeterSequentially(t, (MeterIDStop/4*3)+1, MeterIDStop, 1600, 1600, &wg)
827 //2. Verify that the device state is proper after updating so many meters
828 err := tu.VerifyDevices(stub, NumOfONUsPerOLT)
829 assert.Nil(t, err)
830 wg.Wait()
831
832 //3. Refresh logical device cache
833 err = refreshLocalDeviceCache(stub)
834 assert.Nil(t, err)
835
836 //4. Verify that all the meters got modified
837 for meterID := MeterIDStart; meterID <= MeterIDStop; meterID++ {
838 fmt.Println("Verifying meter ID :", meterID)
839 verifyMeter(t, uint32(meterID), 1600, 1600, 0)
840 }
841}
842
843func TestMultipleMeterDelSequential(t *testing.T) {
844 var wg sync.WaitGroup
845 wg.Add(1)
846 //1. Delete all the given meters sequentially
847 delMultipleMeterSequential(t, MeterIDStart, MeterIDStop, &wg)
848 //2. Verify that all the given meters are deleted
849 verifyNoMeters(t)
850}
851
852func TestMultipleFlowsWithMeters(t *testing.T) {
853 err := refreshLocalDeviceCache(stub)
854 assert.Nil(t, err)
855
856 //1. Delete all the previous flows
857 for _, lD := range allLogicalDevices {
858 deleteAllFlows(stub, lD)
859 }
860
861 //2. Add multiple meters for the flows to refer to
862 var wg sync.WaitGroup
863 wg.Add(2)
864 addMultipleMeterSequentially(t, MeterIDStart, 10, 1600, 1600, &wg)
865 // Adding meter verification here again will increase the time taken by the test. So leaving meter verification
866 installMultipleFlowsWithMeter(t, 1, 10, &wg)
867}
868
869func TestFlowDeletionWithMeterDelete(t *testing.T) {
870 err := refreshLocalDeviceCache(stub)
871 assert.Nil(t, err)
872
873 //1. Delete all meters
874 deleteAllMeters(t)
875 //2. Verify that all the meters are deleted
876 verifyNoMeters(t)
877 //3. As no meters are present, so all flows referring to these meters should also be deleted
878 // Flow referring to meterID 1 - 10 were installed in the above test "TestMultipleFlowsWithMeters"
879 err = refreshLocalDeviceCache(stub)
880 assert.Nil(t, err)
881 for _, lD := range allLogicalDevices {
882 verifyNOFlows(t, lD, 100, 101)
883 }
884}
885
886func TestAddFlowWithInvalidMeter(t *testing.T) {
887 var err error
888 for _, ld := range allLogicalDevices {
889 // Adding flows with meter-ID which is not present should throw error stating -
890 // "Meter-referred-by-flow-is-not-found-in-logicaldevice"
891 err = installEapolFlows(stub, ld, 1, 100, 101)
892 assert.NotNil(t, err)
893 }
khenaidoo0458db62019-06-20 08:50:36 -0400894}
895
896func TestMain(m *testing.M) {
897 setup()
898 code := m.Run()
899 shutdown()
900 os.Exit(code)
901}