VOL-2242: Default TP not chosen when TP not available on KV store
- Choose a default TP when given TP table-id is not found on kv store
- Signicant simplication from previous interpretation of instance-control attributes
- Fix logs
- Bump version to 2.2.17
Change-Id: I2e49d9942fdcb00d1354fd51575f26bccedf1471
diff --git a/VERSION b/VERSION
index da36238..c36c648 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.2.17-dev
+2.2.17
diff --git a/pkg/techprofile/tech_profile.go b/pkg/techprofile/tech_profile.go
index 8d391eb..2c0edae 100644
--- a/pkg/techprofile/tech_profile.go
+++ b/pkg/techprofile/tech_profile.go
@@ -290,57 +290,23 @@
var KvTpIns TechProfile
var resPtr *TechProfile = &KvTpIns
var err error
- var tp *DefaultTechProfile = nil
var kvResult *kvstore.KVPair
- if tp = t.getTPFromKVStore(techProfiletblID); tp != nil {
- if err := t.validateInstanceControlAttr(tp.InstanceCtrl); err != nil {
- return nil, errors.New("invalid-instance-ctl-attr")
- }
- } else {
- return nil, errors.New("tp-not-found-on-kv-store")
- }
- if tp.InstanceCtrl.Onu == "multi-instance" {
- // When InstanceCtrl.Onu is "multi-instance" there can be multiple instance of the same
- // TP across different UNIs. We either find a pre-existing TP Instance on that UNI or
- // create a new one.
- log.Infow("Getting tech profile instance from KV store", log.Fields{"path": path})
- kvResult, err = t.config.KVBackend.Get(path)
- } else { // "single-instance"
- // When InstanceCtrl.Onu is "single-instance" there can be only one instance of the
- // TP across all UNIs. The TP instances for the given TP ID will have the same alloc_id,
- // but different gemport-ids (per UNI).
- // We do the following
- // 1. Find a pre-existing TP Instance for the given TP ID and on the given UNI.
- // If exists, return, else step 2.
- // 2. Find TP instance for the given TP ID and on any other UNI on that ONU.
- // If exists, make a copy of the TP instance, replace the gem-port IDs, place it
- // in the the current UNIs TP instance path.
- // If no other UNI have TP instance too, then return nil (a new TP instance will
- // get created for the given TP ID).
- kvResult, err = t.config.KVBackend.Get(path)
- if kvResult == nil {
- if resPtr, err = t.findAndAssignTpInstance(path); resPtr != nil {
- log.Infow("successfully-found-and-assigned-tp-instance", log.Fields{"tpPath": path})
- return resPtr, err
- }
- }
- }
- if err != nil {
- log.Errorw("Error while fetching tech-profile instance from KV backend", log.Fields{"key": path})
- return nil, err
- }
+ kvResult, _ = t.config.KVBackend.Get(path)
if kvResult == nil {
- log.Infow("Tech profile does not exist in KV store", log.Fields{"key": path})
- resPtr = nil
+ log.Infow("tp-instance-not-found-on-kv", log.Fields{"key": path})
+ return nil, nil
} else {
if value, err := kvstore.ToByte(kvResult.Value); err == nil {
if err = json.Unmarshal(value, resPtr); err != nil {
- log.Errorw("Error while unmarshal KV result", log.Fields{"key": path, "value": value})
+ log.Errorw("error-unmarshal-kv-result", log.Fields{"key": path, "value": value})
+ return nil, errors.New("error-unmarshal-kv-result")
+ } else {
+ return resPtr, nil
}
}
}
- return resPtr, err
+ return nil, err
}
func (t *TechProfileMgr) addTechProfInstanceToKVStore(techProfiletblID uint32, uniPortName string, tpInstance *TechProfile) error {
@@ -378,7 +344,7 @@
}
func (t *TechProfileMgr) CreateTechProfInstance(techProfiletblID uint32, uniPortName string, intfId uint32) *TechProfile {
var tpInstance *TechProfile
- log.Infow("Creating tech profile instance ", log.Fields{"tableid": techProfiletblID, "uni": uniPortName, "intId": intfId})
+ log.Infow("creating-tp-instance", log.Fields{"tableid": techProfiletblID, "uni": uniPortName, "intId": intfId})
// Make sure the uniPortName is as per format pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}
if !uniPortNameFormat.Match([]byte(uniPortName)) {
@@ -388,17 +354,26 @@
tp := t.getTPFromKVStore(techProfiletblID)
if tp != nil {
- log.Infow("Creating tech profile instance with profile from KV store", log.Fields{"tpid": techProfiletblID})
+ if err := t.validateInstanceControlAttr(tp.InstanceCtrl); err != nil {
+ log.Error("invalid-instance-ctrl-attr--using-default-tp")
+ tp = t.getDefaultTechProfile()
+ } else {
+ log.Infow("using-specified-tp-from-kv-store", log.Fields{"tpid": techProfiletblID})
+ }
} else {
+ log.Info("tp-not-found-on-kv--creating-default-tp")
tp = t.getDefaultTechProfile()
- log.Infow("Creating tech profile instance with default values", log.Fields{"tpid": techProfiletblID})
}
- tpInstance = t.allocateTPInstance(uniPortName, tp, intfId)
- if err := t.addTechProfInstanceToKVStore(techProfiletblID, uniPortName, tpInstance); err != nil {
- log.Errorw("Error in adding tech profile instance to KV ", log.Fields{"tableid": techProfiletblID, "uni": uniPortName})
+ tpInstancePath := t.GetTechProfileInstanceKVPath(techProfiletblID, uniPortName)
+ if tpInstance = t.allocateTPInstance(uniPortName, tp, intfId, tpInstancePath); tpInstance == nil {
+ log.Error("tp-intance-allocation-failed")
return nil
}
- log.Infow("Added tech profile instance to KV store successfully ",
+ if err := t.addTechProfInstanceToKVStore(techProfiletblID, uniPortName, tpInstance); err != nil {
+ log.Errorw("error-adding-tp-to-kv-store ", log.Fields{"tableid": techProfiletblID, "uni": uniPortName})
+ return nil
+ }
+ log.Infow("tp-added-to-kv-store-successfully",
log.Fields{"tpid": techProfiletblID, "uni": uniPortName, "intfId": intfId})
return tpInstance
}
@@ -427,7 +402,7 @@
return nil
}
-func (t *TechProfileMgr) allocateTPInstance(uniPortName string, tp *DefaultTechProfile, intfId uint32) *TechProfile {
+func (t *TechProfileMgr) allocateTPInstance(uniPortName string, tp *DefaultTechProfile, intfId uint32, tpInstPath string) *TechProfile {
var usGemPortAttributeList []iGemPortAttribute
var dsGemPortAttributeList []iGemPortAttribute
@@ -437,15 +412,24 @@
log.Infow("Allocating TechProfileMgr instance from techprofile template", log.Fields{"uniPortName": uniPortName, "intfId": intfId, "numGem": tp.NumGemPorts})
- err = t.validateInstanceControlAttr(tp.InstanceCtrl)
- if err != nil {
- log.Error("invalid-tp-instance-control-attributes")
- return nil
- }
-
- if tcontIDs, err = t.resourceMgr.GetResourceID(intfId, t.resourceMgr.GetResourceTypeAllocID(), 1); err != nil {
- log.Errorw("Error getting alloc id from rsrcrMgr", log.Fields{"intfId": intfId})
- return nil
+ if tp.InstanceCtrl.Onu == "multi-instance" {
+ if tcontIDs, err = t.resourceMgr.GetResourceID(intfId, t.resourceMgr.GetResourceTypeAllocID(), 1); err != nil {
+ log.Errorw("Error getting alloc id from rsrcrMgr", log.Fields{"intfId": intfId})
+ return nil
+ }
+ } else { // "single-instance"
+ tpInst, err := t.getSingleInstanceTp(tpInstPath)
+ if tpInst == nil {
+ // No "single-instance" tp found on one any uni port for the given TP ID
+ // Allocate a new TcontID or AllocID
+ if tcontIDs, err = t.resourceMgr.GetResourceID(intfId, t.resourceMgr.GetResourceTypeAllocID(), 1); err != nil {
+ log.Errorw("Error getting alloc id from rsrcrMgr", log.Fields{"intfId": intfId})
+ return nil
+ }
+ } else {
+ // Use the alloc-id from the existing TpInstance
+ tcontIDs = append(tcontIDs, tpInst.UsScheduler.AllocID)
+ }
}
log.Debugw("Num GEM ports in TP:", log.Fields{"NumGemPorts": tp.NumGemPorts})
if gemPorts, err = t.resourceMgr.GetResourceID(intfId, t.resourceMgr.GetResourceTypeGemPortID(), tp.NumGemPorts); err != nil {
@@ -500,21 +484,10 @@
DownstreamGemPortAttributeList: dsGemPortAttributeList}
}
-// findAndAssignTpInstance finds out if there is another TpInstance for an ONU on a different
-// uni port for the same TP ID.
-// If it finds one:
-// 1. It will make a copy of the TpInstance
-// 2. Retain the AllocID
-// 3. Replace the GemPort IDs
-// 4. Copy the new TpInstance on the given tpPath
-// ** NOTE ** : This is to be used only when the instance control attribute is as below
-// uni: single-instance, onu: single-instance
-func (t *TechProfileMgr) findAndAssignTpInstance(tpPath string) (*TechProfile, error) {
+// getSingleInstanceTp returns another TpInstance for an ONU on a different
+// uni port for the same TP ID, if it finds one, else nil.
+func (t *TechProfileMgr) getSingleInstanceTp(tpPath string) (*TechProfile, error) {
var tpInst TechProfile
- var foundValidTpInst = false
- var gemPortIDs []uint32
- var intfID uint64
- var err error
// For example:
// tpPath like "service/voltha/technology_profiles/xgspon/64/pon-{0}/onu-{1}/uni-{1}"
@@ -522,19 +495,6 @@
uniPathSlice := regexp.MustCompile(`/uni-{[0-9]+}$`).Split(tpPath, 2)
kvPairs, _ := t.config.KVBackend.List(uniPathSlice[0])
- // Find the PON interface ID from the TP Path
- var tpPathRgx = regexp.MustCompile(`pon-{([0-9]+)}`)
- intfStrMatch := tpPathRgx.FindStringSubmatch(tpPath)
- if intfStrMatch == nil {
- log.Error("could-not-find-pon-intf-id-in-tp-path")
- return nil, errors.New("could-not-find-pon-intf-id-in-tp-path")
- } else {
- if intfID, err = strconv.ParseUint(intfStrMatch[1], 10, 64); err != nil {
- log.Errorw("error-converting-pon-intfid-str-to-unint", log.Fields{"intfIdStr": intfStrMatch[1]})
- return nil, errors.New("error-converting-pon-intfid-str-to-unint")
- }
- }
-
// Find a valid TP Instance among all the UNIs of that ONU for the given TP ID
for keyPath, kvPair := range kvPairs {
if value, err := kvstore.ToByte(kvPair.Value); err == nil {
@@ -543,39 +503,10 @@
return nil, errors.New("error-unmarshal-kv-pair")
} else {
log.Debugw("found-valid-tp-instance-on-another-uni", log.Fields{"keyPath": keyPath})
- foundValidTpInst = true
- break
+ return &tpInst, nil
}
}
}
- if foundValidTpInst {
- // Get new GemPort IDs
- if gemPortIDs, err = t.resourceMgr.GetResourceID(uint32(intfID), t.resourceMgr.GetResourceTypeGemPortID(), tpInst.NumGemPorts); err != nil {
- log.Errorw("gem-port-assignment-failed", log.Fields{"intfId": intfID, "numGemports": tpInst.NumGemPorts})
- return nil, errors.New("gem-port-assignment-failed")
- }
- // Update the new GemPort IDs to the TpInstance
- for i := 0; i < int(tpInst.NumGemPorts); i++ {
- tpInst.DownstreamGemPortAttributeList[i].GemportID = gemPortIDs[i]
- tpInst.UpstreamGemPortAttributeList[i].GemportID = gemPortIDs[i]
- }
-
- tpInstanceJson, err := json.Marshal(tpInst)
- if err == nil {
- // Backend will convert JSON byte array into string format
- log.Debugw("store-tp-instance", log.Fields{"tpPath": tpPath, "val": tpInstanceJson})
- if err = t.config.KVBackend.Put(tpPath, tpInstanceJson); err != nil {
- return nil, errors.New("error-store-instance-on-kv")
- }
- // We have succesfully placed the new TP Instance if we land here.
- log.Debugw("successfully-placed-single-instance-tp-for-tp-path", log.Fields{"tpPath": tpPath})
- return &tpInst, nil
- } else {
- log.Errorw("error-marshal-tp-to-json", log.Fields{"tpPath": tpPath, "tpInstance": tpInst})
- return nil, errors.New("error-marshal-tp-to-json")
- }
- }
- log.Debug("no-pre-existing-tp-instance-found-on-another-uni")
return nil, nil
}