github.com/opencord/voltha-go@v2.2.0+incompatible/db/model/proxy_load_test.go (about)

     1  /*
     2   * Copyright 2018-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.
    15   */
    16  package model
    17  
    18  import (
    19  	"context"
    20  	"encoding/hex"
    21  	"github.com/google/uuid"
    22  	"github.com/opencord/voltha-go/common/log"
    23  	"github.com/opencord/voltha-protos/go/common"
    24  	"github.com/opencord/voltha-protos/go/openflow_13"
    25  	"github.com/opencord/voltha-protos/go/voltha"
    26  	"math/rand"
    27  	"reflect"
    28  	"strconv"
    29  	"sync"
    30  	"testing"
    31  )
    32  
    33  var (
    34  	BenchmarkProxy_Root        *root
    35  	BenchmarkProxy_DeviceProxy *Proxy
    36  	BenchmarkProxy_PLT         *proxyLoadTest
    37  	BenchmarkProxy_Logger      log.Logger
    38  )
    39  
    40  type proxyLoadChanges struct {
    41  	ID     string
    42  	Before interface{}
    43  	After  interface{}
    44  }
    45  type proxyLoadTest struct {
    46  	mutex sync.RWMutex
    47  
    48  	addMutex     sync.RWMutex
    49  	addedDevices []string
    50  
    51  	firmwareMutex    sync.RWMutex
    52  	updatedFirmwares []proxyLoadChanges
    53  	flowMutex        sync.RWMutex
    54  	updatedFlows     []proxyLoadChanges
    55  
    56  	preAddExecuted     bool
    57  	postAddExecuted    bool
    58  	preUpdateExecuted  bool
    59  	postUpdateExecuted bool
    60  }
    61  
    62  func (plt *proxyLoadTest) SetPreAddExecuted(status bool) {
    63  	plt.mutex.Lock()
    64  	defer plt.mutex.Unlock()
    65  	plt.preAddExecuted = status
    66  }
    67  func (plt *proxyLoadTest) SetPostAddExecuted(status bool) {
    68  	plt.mutex.Lock()
    69  	defer plt.mutex.Unlock()
    70  	plt.postAddExecuted = status
    71  }
    72  func (plt *proxyLoadTest) SetPreUpdateExecuted(status bool) {
    73  	plt.mutex.Lock()
    74  	defer plt.mutex.Unlock()
    75  	plt.preUpdateExecuted = status
    76  }
    77  func (plt *proxyLoadTest) SetPostUpdateExecuted(status bool) {
    78  	plt.mutex.Lock()
    79  	defer plt.mutex.Unlock()
    80  	plt.postUpdateExecuted = status
    81  }
    82  
    83  func init() {
    84  	BenchmarkProxy_Root = NewRoot(&voltha.Voltha{}, nil)
    85  
    86  	BenchmarkProxy_Logger, _ = log.AddPackage(log.JSON, log.DebugLevel, log.Fields{"instanceId": "PLT"})
    87  	//log.UpdateAllLoggers(log.Fields{"instanceId": "PROXY_LOAD_TEST"})
    88  	//Setup default logger - applies for packages that do not have specific logger set
    89  	if _, err := log.SetDefaultLogger(log.JSON, log.DebugLevel, log.Fields{"instanceId": "PLT"}); err != nil {
    90  		log.With(log.Fields{"error": err}).Fatal("Cannot setup logging")
    91  	}
    92  
    93  	// Update all loggers (provisioned via init) with a common field
    94  	if err := log.UpdateAllLoggers(log.Fields{"instanceId": "PLT"}); err != nil {
    95  		log.With(log.Fields{"error": err}).Fatal("Cannot setup logging")
    96  	}
    97  	log.SetPackageLogLevel("github.com/opencord/voltha-go/db/model", log.DebugLevel)
    98  
    99  	BenchmarkProxy_DeviceProxy = BenchmarkProxy_Root.node.CreateProxy(context.Background(), "/", false)
   100  	// Register ADD instructions callbacks
   101  	BenchmarkProxy_PLT = &proxyLoadTest{}
   102  
   103  	BenchmarkProxy_DeviceProxy.RegisterCallback(PRE_ADD, commonCallbackFunc, "PRE_ADD", BenchmarkProxy_PLT.SetPreAddExecuted)
   104  	BenchmarkProxy_DeviceProxy.RegisterCallback(POST_ADD, commonCallbackFunc, "POST_ADD", BenchmarkProxy_PLT.SetPostAddExecuted)
   105  
   106  	//// Register UPDATE instructions callbacks
   107  	BenchmarkProxy_DeviceProxy.RegisterCallback(PRE_UPDATE, commonCallbackFunc, "PRE_UPDATE", BenchmarkProxy_PLT.SetPreUpdateExecuted)
   108  	BenchmarkProxy_DeviceProxy.RegisterCallback(POST_UPDATE, commonCallbackFunc, "POST_UPDATE", BenchmarkProxy_PLT.SetPostUpdateExecuted)
   109  
   110  }
   111  
   112  func BenchmarkProxy_AddDevice(b *testing.B) {
   113  	defer GetProfiling().Report()
   114  	b.RunParallel(func(pb *testing.PB) {
   115  		b.Log("Started adding devices")
   116  		for pb.Next() {
   117  			ltPorts := []*voltha.Port{
   118  				{
   119  					PortNo:     123,
   120  					Label:      "lt-port-0",
   121  					Type:       voltha.Port_PON_OLT,
   122  					AdminState: common.AdminState_ENABLED,
   123  					OperStatus: common.OperStatus_ACTIVE,
   124  					DeviceId:   "lt-port-0-device-id",
   125  					Peers:      []*voltha.Port_PeerPort{},
   126  				},
   127  			}
   128  
   129  			ltStats := &openflow_13.OfpFlowStats{
   130  				Id: 1000,
   131  			}
   132  			ltFlows := &openflow_13.Flows{
   133  				Items: []*openflow_13.OfpFlowStats{ltStats},
   134  			}
   135  			ltDevice := &voltha.Device{
   136  				Id:         "",
   137  				Type:       "simulated_olt",
   138  				Address:    &voltha.Device_HostAndPort{HostAndPort: "1.2.3.4:5555"},
   139  				AdminState: voltha.AdminState_PREPROVISIONED,
   140  				Flows:      ltFlows,
   141  				Ports:      ltPorts,
   142  			}
   143  
   144  			ltDevIDBin, _ := uuid.New().MarshalBinary()
   145  			ltDevID := "0001" + hex.EncodeToString(ltDevIDBin)[:12]
   146  			ltDevice.Id = ltDevID
   147  
   148  			BenchmarkProxy_PLT.SetPreAddExecuted(false)
   149  			BenchmarkProxy_PLT.SetPostAddExecuted(false)
   150  
   151  			var added interface{}
   152  			// Add the device
   153  			if added = BenchmarkProxy_DeviceProxy.AddWithID(context.Background(), "/devices", ltDevID, ltDevice, ""); added == nil {
   154  				BenchmarkProxy_Logger.Errorf("Failed to add device: %+v", ltDevice)
   155  				continue
   156  			} else {
   157  				BenchmarkProxy_Logger.Infof("Device was added 1: %+v", added)
   158  			}
   159  
   160  			BenchmarkProxy_PLT.addMutex.Lock()
   161  			BenchmarkProxy_PLT.addedDevices = append(BenchmarkProxy_PLT.addedDevices, added.(*voltha.Device).Id)
   162  			BenchmarkProxy_PLT.addMutex.Unlock()
   163  		}
   164  	})
   165  
   166  	BenchmarkProxy_Logger.Infof("Number of added devices : %d", len(BenchmarkProxy_PLT.addedDevices))
   167  }
   168  
   169  func BenchmarkProxy_UpdateFirmware(b *testing.B) {
   170  	b.RunParallel(func(pb *testing.PB) {
   171  		for pb.Next() {
   172  			//for i:=0; i < b.N; i++ {
   173  
   174  			if len(BenchmarkProxy_PLT.addedDevices) > 0 {
   175  				var target interface{}
   176  				randomID := BenchmarkProxy_PLT.addedDevices[rand.Intn(len(BenchmarkProxy_PLT.addedDevices))]
   177  				firmProxy := BenchmarkProxy_Root.node.CreateProxy(context.Background(), "/", false)
   178  				if target = firmProxy.Get(context.Background(), "/devices/"+randomID, 0, false,
   179  					""); !reflect.ValueOf(target).IsValid() {
   180  					BenchmarkProxy_Logger.Errorf("Failed to find device: %s %+v", randomID, target)
   181  					continue
   182  				}
   183  
   184  				BenchmarkProxy_PLT.SetPreUpdateExecuted(false)
   185  				BenchmarkProxy_PLT.SetPostUpdateExecuted(false)
   186  				firmProxy.RegisterCallback(PRE_UPDATE, commonCallbackFunc, "PRE_UPDATE", BenchmarkProxy_PLT.SetPreUpdateExecuted)
   187  				firmProxy.RegisterCallback(POST_UPDATE, commonCallbackFunc, "POST_UPDATE", BenchmarkProxy_PLT.SetPostUpdateExecuted)
   188  
   189  				var fwVersion int
   190  
   191  				before := target.(*voltha.Device).FirmwareVersion
   192  				if target.(*voltha.Device).FirmwareVersion == "n/a" {
   193  					fwVersion = 0
   194  				} else {
   195  					fwVersion, _ = strconv.Atoi(target.(*voltha.Device).FirmwareVersion)
   196  					fwVersion++
   197  				}
   198  
   199  				target.(*voltha.Device).FirmwareVersion = strconv.Itoa(fwVersion)
   200  				after := target.(*voltha.Device).FirmwareVersion
   201  
   202  				var updated interface{}
   203  				if updated = firmProxy.Update(context.Background(), "/devices/"+randomID, target.(*voltha.Device), false,
   204  					""); updated == nil {
   205  					BenchmarkProxy_Logger.Errorf("Failed to update device: %+v", target)
   206  					continue
   207  				} else {
   208  					BenchmarkProxy_Logger.Infof("Device was updated : %+v", updated)
   209  
   210  				}
   211  
   212  				if d := firmProxy.Get(context.Background(), "/devices/"+randomID, 0, false,
   213  					""); !reflect.ValueOf(d).IsValid() {
   214  					BenchmarkProxy_Logger.Errorf("Failed to get device: %s", randomID)
   215  					continue
   216  				} else if d.(*voltha.Device).FirmwareVersion == after {
   217  					BenchmarkProxy_Logger.Infof("Imm Device was updated with new value: %s %+v", randomID, d)
   218  				} else if d.(*voltha.Device).FirmwareVersion == before {
   219  					BenchmarkProxy_Logger.Errorf("Imm Device kept old value: %s %+v %+v", randomID, d, target)
   220  				} else {
   221  					BenchmarkProxy_Logger.Errorf("Imm Device has unknown value: %s %+v %+v", randomID, d, target)
   222  				}
   223  
   224  				BenchmarkProxy_PLT.firmwareMutex.Lock()
   225  
   226  				BenchmarkProxy_PLT.updatedFirmwares = append(
   227  					BenchmarkProxy_PLT.updatedFirmwares,
   228  					proxyLoadChanges{ID: randomID, Before: before, After: after},
   229  				)
   230  				BenchmarkProxy_PLT.firmwareMutex.Unlock()
   231  			}
   232  		}
   233  	})
   234  }
   235  
   236  func traverseBranches(revision Revision, depth int) {
   237  	if revision == nil {
   238  		return
   239  	}
   240  	prefix := strconv.Itoa(depth) + " ~~~~ "
   241  	for i := 0; i < depth; i++ {
   242  		prefix += "  "
   243  	}
   244  
   245  	BenchmarkProxy_Logger.Debugf("%sRevision: %s %+v", prefix, revision.GetHash(), revision.GetData())
   246  
   247  	//for brIdx, brRev := range revision.GetBranch().Revisions {
   248  	//	BenchmarkProxy_Logger.Debugf("%sbranchIndex: %s", prefix, brIdx)
   249  	//	traverseBranches(brRev, depth+1)
   250  	//}
   251  	for childrenI, children := range revision.GetAllChildren() {
   252  		BenchmarkProxy_Logger.Debugf("%schildrenIndex: %s, length: %d", prefix, childrenI, len(children))
   253  
   254  		for _, subrev := range children {
   255  			//subrev.GetBranch().Latest
   256  			traverseBranches(subrev, depth+1)
   257  		}
   258  	}
   259  
   260  }
   261  func BenchmarkProxy_UpdateFlows(b *testing.B) {
   262  	b.RunParallel(func(pb *testing.PB) {
   263  		for pb.Next() {
   264  			if len(BenchmarkProxy_PLT.addedDevices) > 0 {
   265  				randomID := BenchmarkProxy_PLT.addedDevices[rand.Intn(len(BenchmarkProxy_PLT.addedDevices))]
   266  
   267  				flowsProxy := BenchmarkProxy_Root.node.CreateProxy(context.Background(), "/devices/"+randomID+"/flows", false)
   268  				flows := flowsProxy.Get(context.Background(), "/", 0, false, "")
   269  
   270  				before := flows.(*openflow_13.Flows).Items[0].TableId
   271  				flows.(*openflow_13.Flows).Items[0].TableId = uint32(rand.Intn(3000))
   272  				after := flows.(*openflow_13.Flows).Items[0].TableId
   273  
   274  				flowsProxy.RegisterCallback(
   275  					PRE_UPDATE,
   276  					commonCallback2,
   277  				)
   278  				flowsProxy.RegisterCallback(
   279  					POST_UPDATE,
   280  					commonCallback2,
   281  				)
   282  
   283  				var updated interface{}
   284  				if updated = flowsProxy.Update(context.Background(), "/", flows.(*openflow_13.Flows), false, ""); updated == nil {
   285  					b.Errorf("Failed to update flows for device: %+v", flows)
   286  				} else {
   287  					BenchmarkProxy_Logger.Infof("Flows were updated : %+v", updated)
   288  				}
   289  				BenchmarkProxy_PLT.flowMutex.Lock()
   290  				BenchmarkProxy_PLT.updatedFlows = append(
   291  					BenchmarkProxy_PLT.updatedFlows,
   292  					proxyLoadChanges{ID: randomID, Before: before, After: after},
   293  				)
   294  				BenchmarkProxy_PLT.flowMutex.Unlock()
   295  			}
   296  		}
   297  	})
   298  }
   299  
   300  func BenchmarkProxy_GetDevices(b *testing.B) {
   301  	//traverseBranches(BenchmarkProxy_DeviceProxy.Root.node.Branches[NONE].GetLatest(), 0)
   302  
   303  	for i := 0; i < len(BenchmarkProxy_PLT.addedDevices); i++ {
   304  		devToGet := BenchmarkProxy_PLT.addedDevices[i]
   305  		// Verify that the added device can now be retrieved
   306  		if d := BenchmarkProxy_DeviceProxy.Get(context.Background(), "/devices/"+devToGet, 0, false,
   307  			""); !reflect.ValueOf(d).IsValid() {
   308  			BenchmarkProxy_Logger.Errorf("Failed to get device: %s", devToGet)
   309  			continue
   310  		} else {
   311  			BenchmarkProxy_Logger.Infof("Got device: %s %+v", devToGet, d)
   312  		}
   313  	}
   314  }
   315  
   316  func BenchmarkProxy_GetUpdatedFirmware(b *testing.B) {
   317  	for i := 0; i < len(BenchmarkProxy_PLT.updatedFirmwares); i++ {
   318  		devToGet := BenchmarkProxy_PLT.updatedFirmwares[i].ID
   319  		// Verify that the updated device can be retrieved and that the updates were actually applied
   320  		if d := BenchmarkProxy_DeviceProxy.Get(context.Background(), "/devices/"+devToGet, 0, false,
   321  			""); !reflect.ValueOf(d).IsValid() {
   322  			BenchmarkProxy_Logger.Errorf("Failed to get device: %s", devToGet)
   323  			continue
   324  		} else if d.(*voltha.Device).FirmwareVersion == BenchmarkProxy_PLT.updatedFirmwares[i].After.(string) {
   325  			BenchmarkProxy_Logger.Infof("Device was updated with new value: %s %+v", devToGet, d)
   326  		} else if d.(*voltha.Device).FirmwareVersion == BenchmarkProxy_PLT.updatedFirmwares[i].Before.(string) {
   327  			BenchmarkProxy_Logger.Errorf("Device kept old value: %s %+v %+v", devToGet, d, BenchmarkProxy_PLT.updatedFirmwares[i])
   328  		} else {
   329  			BenchmarkProxy_Logger.Errorf("Device has unknown value: %s %+v %+v", devToGet, d, BenchmarkProxy_PLT.updatedFirmwares[i])
   330  		}
   331  	}
   332  }