| /* |
| * Copyright 2020-present Open Networking Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| //Package adaptercoreonu provides the utility for onu devices, flows and statistics |
| package adaptercoreonu |
| |
| import ( |
| "context" |
| "encoding/json" |
| "sync" |
| |
| "github.com/opencord/voltha-lib-go/v3/pkg/db" |
| "github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore" |
| "github.com/opencord/voltha-lib-go/v3/pkg/log" |
| tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile" |
| ) |
| |
| const cBasePathTechProfileKVStore = "service/voltha/technology_profiles" |
| |
| type resourceEntry int |
| |
| const ( |
| cResourceGemPort resourceEntry = 1 |
| cResourceTcont resourceEntry = 2 |
| ) |
| |
| type onuSerialNumber struct { |
| sliceVendorID []byte |
| sliceVendorSpecific []byte |
| } |
| |
| type onuPersistentData struct { |
| persOnuID uint32 |
| persIntfID uint32 |
| persSnr onuSerialNumber |
| persAdminState string |
| persOperState string |
| persUniTpPath map[uint32]string |
| persUniTpData map[uint32]tp.TechProfile |
| } |
| |
| //OnuUniTechProf structure holds information about the TechProfiles attached to Uni Ports of the ONU |
| type OnuUniTechProf struct { |
| deviceID string |
| baseDeviceHandler *DeviceHandler |
| tpProcMutex sync.RWMutex |
| sOnuPersistentData onuPersistentData |
| techProfileKVStore *db.Backend |
| } |
| |
| //NewOnuUniTechProf returns the instance of a OnuUniTechProf |
| //(one instance per ONU/deviceHandler for all possible UNI's) |
| func NewOnuUniTechProf(ctx context.Context, aDeviceID string, aDeviceHandler *DeviceHandler) *OnuUniTechProf { |
| logger.Infow("init-OnuUniTechProf", log.Fields{"deviceId": aDeviceID}) |
| var onuTP OnuUniTechProf |
| onuTP.deviceID = aDeviceID |
| onuTP.baseDeviceHandler = aDeviceHandler |
| onuTP.tpProcMutex = sync.RWMutex{} |
| onuTP.sOnuPersistentData.persUniTpPath = make(map[uint32]string) |
| onuTP.sOnuPersistentData.persUniTpData = make(map[uint32]tp.TechProfile) |
| |
| onuTP.techProfileKVStore = aDeviceHandler.SetBackend(cBasePathTechProfileKVStore) |
| if onuTP.techProfileKVStore == nil { |
| logger.Errorw("Can't access techProfileKVStore - no backend connection to service", |
| log.Fields{"deviceID": aDeviceID, "service": cBasePathTechProfileKVStore}) |
| } |
| return &onuTP |
| } |
| |
| // lockTpProcMutex locks OnuUniTechProf processing mutex |
| func (onuTP *OnuUniTechProf) lockTpProcMutex() { |
| onuTP.tpProcMutex.Lock() |
| } |
| |
| // unlockTpProcMutex unlocks OnuUniTechProf processing mutex |
| func (onuTP *OnuUniTechProf) unlockTpProcMutex() { |
| onuTP.tpProcMutex.Unlock() |
| } |
| |
| // updateOnuUniTpPath verifies and updates changes in the kvStore onuUniTpPath |
| func (onuTP *OnuUniTechProf) updateOnuUniTpPath(aUniID uint32, aPathString string) bool { |
| /* within some specific InterAdapter processing request write/read access to data is ensured to be sequentially, |
| as also the complete sequence is ensured to 'run to completion' before some new request is accepted |
| no specific concurrency protection to sOnuPersistentData is required here |
| */ |
| if existingPath, present := onuTP.sOnuPersistentData.persUniTpPath[aUniID]; present { |
| // uni entry already exists |
| //logger.Debugw(" already exists", log.Fields{"for InstanceId": a_uniInstNo}) |
| if existingPath != aPathString { |
| if aPathString == "" { |
| //existing entry to be deleted |
| logger.Debugw("UniTp path delete", log.Fields{ |
| "deviceID": onuTP.deviceID, "uniID": aUniID, "path": aPathString}) |
| delete(onuTP.sOnuPersistentData.persUniTpPath, aUniID) |
| } else { |
| //existing entry to be modified |
| logger.Debugw("UniTp path modify", log.Fields{ |
| "deviceID": onuTP.deviceID, "uniID": aUniID, "path": aPathString}) |
| onuTP.sOnuPersistentData.persUniTpPath[aUniID] = aPathString |
| } |
| return true |
| } |
| //entry already exists |
| logger.Debugw("UniTp path already exists", log.Fields{ |
| "deviceID": onuTP.deviceID, "uniID": aUniID, "path": aPathString}) |
| return false |
| } |
| //uni entry does not exist |
| if aPathString == "" { |
| //delete request in non-existing state , accept as no change |
| logger.Debugw("UniTp path already removed", log.Fields{ |
| "deviceID": onuTP.deviceID, "uniID": aUniID}) |
| return false |
| } |
| //new entry to be set |
| logger.Debugw("New UniTp path set", log.Fields{ |
| "deviceID": onuTP.deviceID, "uniID": aUniID, "path": aPathString}) |
| onuTP.sOnuPersistentData.persUniTpPath[aUniID] = aPathString |
| return true |
| } |
| |
| func (onuTP *OnuUniTechProf) configureUniTp(aUniID uint32, aPathString string, wg *sync.WaitGroup) { |
| defer wg.Done() |
| logger.Debugw("configure the Uni according to TpPath", log.Fields{ |
| "deviceID": onuTP.deviceID, "uniID": aUniID, "path": aPathString}) |
| |
| //TODO!!! |
| // reaction on existing tp, deletion of tp, start the corresponding OMCI configuation of the UNI port |
| |
| if onuTP.techProfileKVStore == nil { |
| logger.Debug("techProfileKVStore not set - abort") |
| return |
| } |
| |
| Value, err := onuTP.techProfileKVStore.Get(context.TODO(), aPathString) |
| if err == nil { |
| if Value != nil { |
| logger.Debugw("tech-profile read", |
| log.Fields{"Key": Value.Key, "Value": Value.Value}) |
| tpTmpBytes, _ := kvstore.ToByte(Value.Value) |
| |
| var tpInst tp.TechProfile |
| if err = json.Unmarshal(tpTmpBytes, &tpInst); err != nil { |
| logger.Errorw("TechProf - Failed to unmarshal tech-profile into tpInst", |
| log.Fields{"error": err, "device-id": onuTP.deviceID}) |
| } else { |
| logger.Debugw("TechProf - tpInst", log.Fields{"tpInst": tpInst}) |
| onuTP.sOnuPersistentData.persUniTpData[aUniID] = tpInst |
| |
| // access examples |
| logger.Debugw("TechProf - name", |
| log.Fields{"onuTP.sOnuPersistentData.persUniTpData[aUniID].Name": onuTP.sOnuPersistentData.persUniTpData[aUniID].Name}) |
| // |
| logger.Debugw("TechProf - instance_control.max_gem_payload_size", |
| log.Fields{"onuTP.sOnuPersistentData.persUniTpData[aUniID].InstanceCtrl.MaxGemPayloadSize": onuTP.sOnuPersistentData.persUniTpData[aUniID].InstanceCtrl.MaxGemPayloadSize}) |
| // |
| logger.Debugw("TechProf - downstream_gem_port_attribute_list.discard_config.max_threshold", |
| log.Fields{"onuTP.sOnuPersistentData.persUniTpData[aUniID].DownstreamGemPortAttributeList[0].DiscardConfig.MaxThreshold": onuTP.sOnuPersistentData.persUniTpData[aUniID].DownstreamGemPortAttributeList[0].DiscardConfig.MaxThreshold}) |
| } |
| } else { |
| logger.Debugw("No tech-profile found", log.Fields{"path": aPathString, "device-id": onuTP.deviceID}) |
| } |
| } else { |
| logger.Errorw("kvstore-get failed for path", |
| log.Fields{"path": aPathString, "device-id": onuTP.deviceID}) |
| } |
| } |
| |
| func (onuTP *OnuUniTechProf) updateOnuTpPathKvStore(wg *sync.WaitGroup) { |
| defer wg.Done() |
| logger.Debugw("this would update the ONU's TpPath in KVStore", log.Fields{ |
| "deviceID": onuTP.deviceID}) |
| //TODO!!! |
| //make use of onuTP.sOnuPersistentData to store the TpPath to KVStore |
| } |
| |
| // deleteTpRessource removes ressources from the ONU's specified Uni |
| func (onuTP *OnuUniTechProf) deleteTpRessource(aUniID uint32, aPathString string, |
| aRessource resourceEntry, aEntryID uint32, wg *sync.WaitGroup) { |
| defer wg.Done() |
| logger.Debugw("this would remove TP resources from ONU's UNI", log.Fields{ |
| "deviceID": onuTP.deviceID, "uniID": aUniID, "path": aPathString, "ressource": aRessource}) |
| //TODO!!! |
| } |
| |
| func (onuTP *OnuUniTechProf) waitForTpCompletion(wg *sync.WaitGroup) { |
| wg.Wait() |
| logger.Debug("some TechProfile Processing completed") |
| onuTP.tpProcMutex.Unlock() //allow further TP related processing |
| } |