VOL-1943 Adding multi tcont support to openolt adapter

Change-Id: Ibdc18b9c2f1cac3abbc43ba77512484d4574347b
diff --git a/adaptercore/resourcemanager/resourcemanager.go b/adaptercore/resourcemanager/resourcemanager.go
index a6a7921..b43aa2b 100755
--- a/adaptercore/resourcemanager/resourcemanager.go
+++ b/adaptercore/resourcemanager/resourcemanager.go
@@ -37,10 +37,10 @@
 	KvstoreTimeout = 5
 	// BasePathKvStore - service/voltha/openolt/<device_id>
 	BasePathKvStore = "service/voltha/openolt/{%s}"
-	// TpIDPathSuffix - tp_id/<(pon_id, onu_id, uni_id)>
-	TpIDPathSuffix = "tp_id/{%d,%d,%d}"
-	//MeterIDPathSuffix - meter_id/<(pon_id, onu_id, uni_id)>/<direction>
-	MeterIDPathSuffix = "meter_id/{%d,%d,%d}/{%s}"
+	// TpIDPathSuffix - <(pon_id, onu_id, uni_id)>/tp_id
+	TpIDPathSuffix = "{%d,%d,%d}/tp_id"
+	//MeterIDPathSuffix - <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
+	MeterIDPathSuffix = "{%d,%d,%d}/{%d}/meter_id/{%s}"
 )
 
 // FlowInfo holds the flow information
@@ -96,7 +96,7 @@
 	return kvbackend
 }
 
-// NewResourceMgr init a New resource maanger instance which in turn instantiates pon resource manager
+// NewResourceMgr init a New resource manager instance which in turn instantiates pon resource manager
 // instances according to technology. Initializes the default resource ranges for all
 // the resources.
 func NewResourceMgr(deviceID string, KVStoreHostPort string, kvStoreType string, deviceType string, devInfo *openolt.DeviceInfo) *OpenOltResourceMgr {
@@ -123,7 +123,7 @@
 
 	/*
 	   If a legacy driver returns protobuf without any ranges,s synthesize one from
-	   the legacy global per-device informaiton. This, in theory, is temporary until
+	   the legacy global per-device information. This, in theory, is temporary until
 	   the legacy drivers are upgrade to support pool ranges.
 	*/
 	if devInfo.Ranges == nil {
@@ -178,7 +178,7 @@
 		RsrcMgrsByTech[technology], err = ponrmgr.NewPONResourceManager(technology, deviceType, deviceID,
 			Backend, ResourceMgr.Host, ResourceMgr.Port)
 		if err != nil {
-			log.Errorf("Failed to create pon resource manager instacnce for technology %s", technology)
+			log.Errorf("Failed to create pon resource manager instance for technology %s", technology)
 			return nil
 		}
 		// resource_mgrs_by_tech[technology] = resource_mgr
@@ -219,7 +219,7 @@
 
 	/*
 	   Then apply device specific information. If KV doesn't exist
-	   or is broader than the device, the device's informationw ill
+	   or is broader than the device, the device's information will
 	   dictate the range limits
 	*/
 	log.Debugf("Using device info to init pon resource ranges for tech", ponRMgr.Technology)
@@ -517,19 +517,47 @@
 	return RsrcMgr.ResourceMgrs[intfID].GetCurrentGEMPortIDsForOnu(IntfOnuIDUniID)
 }
 
-// GetCurrentAllocIDForOnu returns alloc ids for given pon interface and onu id
-// Currently of all the alloc_ids available, it returns the first alloc_id in the list for tha given ONU
-func (RsrcMgr *OpenOltResourceMgr) GetCurrentAllocIDForOnu(intfID uint32, onuID uint32, uniID uint32) uint32 {
+// GetCurrentAllocIDsForOnu returns alloc ids for given pon interface and onu id
+func (RsrcMgr *OpenOltResourceMgr) GetCurrentAllocIDsForOnu(intfID uint32, onuID uint32, uniID uint32) []uint32 {
 
 	IntfOnuIDUniID := fmt.Sprintf("%d,%d,%d", intfID, onuID, uniID)
 	AllocID := RsrcMgr.ResourceMgrs[intfID].GetCurrentAllocIDForOnu(IntfOnuIDUniID)
 	if AllocID != nil {
-		// Since we support only one alloc_id for the ONU at the moment,
-		// return the first alloc_id in the list, if available, for that
-		// ONU.
-		return AllocID[0]
+		return AllocID
 	}
-	return 0
+	return []uint32{}
+}
+
+// RemoveAllocIDForOnu removes the alloc id for given pon interface, onu id, uni id and alloc id
+func (RsrcMgr *OpenOltResourceMgr) RemoveAllocIDForOnu(intfID uint32, onuID uint32, uniID uint32, allocID uint32) {
+	allocIDs := RsrcMgr.GetCurrentAllocIDsForOnu(intfID, onuID, uniID)
+	for i := 0; i < len(allocIDs); i++ {
+		if allocIDs[i] == allocID {
+			allocIDs = append(allocIDs[:i], allocIDs[i+1:]...)
+			break
+		}
+	}
+	err := RsrcMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocIDs)
+	if err != nil {
+		log.Errorf("Failed to Remove Alloc Id For Onu. IntfID %d onuID %d uniID %d allocID %d",
+			intfID, onuID, uniID, allocID)
+	}
+}
+
+// RemoveGemPortIDForOnu removes the gem port id for given pon interface, onu id, uni id and gem port id
+func (RsrcMgr *OpenOltResourceMgr) RemoveGemPortIDForOnu(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32) {
+	gemPortIDs := RsrcMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
+	for i := 0; i < len(gemPortIDs); i++ {
+		if gemPortIDs[i] == gemPortID {
+			gemPortIDs = append(gemPortIDs[:i], gemPortIDs[i+1:]...)
+			break
+		}
+	}
+	err := RsrcMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs)
+	if err != nil {
+		log.Errorf("Failed to Remove Gem Id For Onu. IntfID %d onuID %d uniID %d gemPortId %d",
+			intfID, onuID, uniID, gemPortID)
+	}
 }
 
 // UpdateGEMportsPonportToOnuMapOnKVStore updates onu and uni id associated with the gem port to the kv store
@@ -557,6 +585,15 @@
 	return nil
 }
 
+// RemoveGEMportPonportToOnuMapOnKVStore removes the relationship between the gem port and pon port
+func (RsrcMgr *OpenOltResourceMgr) RemoveGEMportPonportToOnuMapOnKVStore(GemPort uint32, PonPort uint32) {
+	IntfGEMPortPath := fmt.Sprintf("%d,%d", PonPort, GemPort)
+	err := RsrcMgr.KVStore.Delete(IntfGEMPortPath)
+	if err != nil {
+		log.Errorf("Failed to Remove Gem port-Pon port to onu map on kv store. Gem %d PonPort %d", GemPort, PonPort)
+	}
+}
+
 // GetGEMPortID gets gem port id for a particular pon port, onu id and uni id and then update the resource map on
 // the KV store with the list of gemport_id allocated for the pon_intf_onu_id tuple
 func (RsrcMgr *OpenOltResourceMgr) GetGEMPortID(ponPort uint32, onuID uint32,
@@ -651,6 +688,26 @@
 	}
 }
 
+// FreeAllocID frees AllocID on the PON resource pool and also frees the allocID association
+// for the given OLT device.
+func (RsrcMgr *OpenOltResourceMgr) FreeAllocID(IntfID uint32, onuID uint32,
+	uniID uint32, allocID uint32) {
+	RsrcMgr.RemoveAllocIDForOnu(IntfID, onuID, uniID, allocID)
+	allocIDs := make([]uint32, 0)
+	allocIDs = append(allocIDs, allocID)
+	RsrcMgr.ResourceMgrs[IntfID].FreeResourceID(IntfID, ponrmgr.ALLOC_ID, allocIDs)
+}
+
+// FreeGemPortID frees GemPortID on the PON resource pool and also frees the gemPortID association
+// for the given OLT device.
+func (RsrcMgr *OpenOltResourceMgr) FreeGemPortID(IntfID uint32, onuID uint32,
+	uniID uint32, gemPortID uint32) {
+	RsrcMgr.RemoveGemPortIDForOnu(IntfID, onuID, uniID, gemPortID)
+	gemPortIDs := make([]uint32, 0)
+	gemPortIDs = append(gemPortIDs, gemPortID)
+	RsrcMgr.ResourceMgrs[IntfID].FreeResourceID(IntfID, ponrmgr.GEMPORT_ID, gemPortIDs)
+}
+
 // FreePONResourcesForONU make the pon resources free for a given pon interface and onu id, and the clears the
 // resource map and the onuID associated with (pon_intf_id, gemport_id) tuple,
 func (RsrcMgr *OpenOltResourceMgr) FreePONResourcesForONU(intfID uint32, onuID uint32, uniID uint32) {
@@ -714,10 +771,10 @@
 }
 
 // GetTechProfileIDForOnu fetches Tech-Profile-ID from the KV-Store for the given onu based on the path
-// This path is formed as the following: tp_id/{IntfID, OnuID, UniID}
-func (RsrcMgr *OpenOltResourceMgr) GetTechProfileIDForOnu(IntfID uint32, OnuID uint32, UniID uint32) uint32 {
+// This path is formed as the following: {IntfID, OnuID, UniID}/tp_id
+func (RsrcMgr *OpenOltResourceMgr) GetTechProfileIDForOnu(IntfID uint32, OnuID uint32, UniID uint32) []uint32 {
 	Path := fmt.Sprintf(TpIDPathSuffix, IntfID, OnuID, UniID)
-	var Data uint32
+	var Data []uint32
 	Value, err := RsrcMgr.KVStore.Get(Path)
 	if err == nil {
 		if Value != nil {
@@ -739,9 +796,9 @@
 
 }
 
-// RemoveTechProfileIDForOnu deletes the tech-profile-id  from the KV-Store for the given onu based on the path
-// This path is formed as the following: tp_id/{IntfID, OnuID, UniID}
-func (RsrcMgr *OpenOltResourceMgr) RemoveTechProfileIDForOnu(IntfID uint32, OnuID uint32, UniID uint32) error {
+// RemoveTechProfileIDsForOnu deletes all tech profile ids from the KV-Store for the given onu based on the path
+// This path is formed as the following: {IntfID, OnuID, UniID}/tp_id
+func (RsrcMgr *OpenOltResourceMgr) RemoveTechProfileIDsForOnu(IntfID uint32, OnuID uint32, UniID uint32) error {
 	IntfOnuUniID := fmt.Sprintf(TpIDPathSuffix, IntfID, OnuID, UniID)
 	if err := RsrcMgr.KVStore.Delete(IntfOnuUniID); err != nil {
 		log.Error("Failed to delete techprofile id resource %s in KV store", IntfOnuUniID)
@@ -750,16 +807,47 @@
 	return nil
 }
 
-//UpdateTechProfileIDForOnu updates (put) already present tech-profile-id for the given onu based on the path
-// This path is formed as the following: tp_id/{IntfID, OnuID, UniID}
+// RemoveTechProfileIDForOnu deletes a specific tech profile id from the KV-Store for the given onu based on the path
+// This path is formed as the following: {IntfID, OnuID, UniID}/tp_id
+func (RsrcMgr *OpenOltResourceMgr) RemoveTechProfileIDForOnu(IntfID uint32, OnuID uint32, UniID uint32, TpID uint32) error {
+	tpIDList := RsrcMgr.GetTechProfileIDForOnu(IntfID, OnuID, UniID)
+	for i, tpIDInList := range tpIDList {
+		if tpIDInList == TpID {
+			tpIDList = append(tpIDList[:i], tpIDList[i+1:]...)
+		}
+	}
+	IntfOnuUniID := fmt.Sprintf(TpIDPathSuffix, IntfID, OnuID, UniID)
+	Value, err := json.Marshal(tpIDList)
+	if err != nil {
+		log.Error("failed to Marshal")
+		return err
+	}
+	if err = RsrcMgr.KVStore.Put(IntfOnuUniID, Value); err != nil {
+		log.Errorf("Failed to update resource %s", IntfOnuUniID)
+		return err
+	}
+	return err
+}
+
+// UpdateTechProfileIDForOnu updates (put) already present tech-profile-id for the given onu based on the path
+// This path is formed as the following: {IntfID, OnuID, UniID}/tp_id
 func (RsrcMgr *OpenOltResourceMgr) UpdateTechProfileIDForOnu(IntfID uint32, OnuID uint32,
 	UniID uint32, TpID uint32) error {
 	var Value []byte
 	var err error
 
 	IntfOnuUniID := fmt.Sprintf(TpIDPathSuffix, IntfID, OnuID, UniID)
+
+	tpIDList := RsrcMgr.GetTechProfileIDForOnu(IntfID, OnuID, UniID)
+	for _, value := range tpIDList {
+		if value == TpID {
+			log.Debugf("TpID %d is already in tpIdList for the path %s", TpID, IntfOnuUniID)
+			return err
+		}
+	}
 	log.Debugf("updating tp id %d on path %s", TpID, IntfOnuUniID)
-	Value, err = json.Marshal(TpID)
+	tpIDList = append(tpIDList, TpID)
+	Value, err = json.Marshal(tpIDList)
 	if err != nil {
 		log.Error("failed to Marshal")
 		return err
@@ -772,13 +860,13 @@
 }
 
 // UpdateMeterIDForOnu updates the meter id in the KV-Store for the given onu based on the path
-// This path is formed as the following: tp_id/{IntfID, OnuID, UniID}/direction
+// This path is formed as the following: <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
 func (RsrcMgr *OpenOltResourceMgr) UpdateMeterIDForOnu(Direction string, IntfID uint32, OnuID uint32,
-	UniID uint32, MeterConfig *ofp.OfpMeterConfig) error {
+	UniID uint32, TpID uint32, MeterConfig *ofp.OfpMeterConfig) error {
 	var Value []byte
 	var err error
 
-	IntfOnuUniID := fmt.Sprintf(MeterIDPathSuffix, IntfID, OnuID, UniID, Direction)
+	IntfOnuUniID := fmt.Sprintf(MeterIDPathSuffix, IntfID, OnuID, UniID, TpID, Direction)
 	Value, err = json.Marshal(*MeterConfig)
 	if err != nil {
 		log.Error("failed to Marshal meter config")
@@ -791,10 +879,11 @@
 	return err
 }
 
-// GetMeterIDForOnu fetches the meter-id fromthe kv store for the given onu based on the path
-// This path is formed as the following: tp_id/{IntfID, OnuID, UniID}/direction
-func (RsrcMgr *OpenOltResourceMgr) GetMeterIDForOnu(Direction string, IntfID uint32, OnuID uint32, UniID uint32) (*ofp.OfpMeterConfig, error) {
-	Path := fmt.Sprintf(MeterIDPathSuffix, IntfID, OnuID, UniID, Direction)
+// GetMeterIDForOnu fetches the meter id from the kv store for the given onu based on the path
+// This path is formed as the following: <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
+func (RsrcMgr *OpenOltResourceMgr) GetMeterIDForOnu(Direction string, IntfID uint32, OnuID uint32,
+	UniID uint32, TpID uint32) (*ofp.OfpMeterConfig, error) {
+	Path := fmt.Sprintf(MeterIDPathSuffix, IntfID, OnuID, UniID, TpID, Direction)
 	var meterConfig ofp.OfpMeterConfig
 	Value, err := RsrcMgr.KVStore.Get(Path)
 	if err == nil {
@@ -820,10 +909,11 @@
 	return &meterConfig, err
 }
 
-// RemoveMeterIDForOnu deletes the meter-id from the kV-Store for the given onu based on the path
-// This path is formed as the following: tp_id/{IntfID, OnuID, UniID}/direction
-func (RsrcMgr *OpenOltResourceMgr) RemoveMeterIDForOnu(Direction string, IntfID uint32, OnuID uint32, UniID uint32) error {
-	Path := fmt.Sprintf(MeterIDPathSuffix, IntfID, OnuID, UniID, Direction)
+// RemoveMeterIDForOnu deletes the meter id from the kV-Store for the given onu based on the path
+// This path is formed as the following: <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
+func (RsrcMgr *OpenOltResourceMgr) RemoveMeterIDForOnu(Direction string, IntfID uint32, OnuID uint32,
+	UniID uint32, TpID uint32) error {
+	Path := fmt.Sprintf(MeterIDPathSuffix, IntfID, OnuID, UniID, TpID, Direction)
 	if err := RsrcMgr.KVStore.Delete(Path); err != nil {
 		log.Errorf("Failed to delete meter id %s from kvstore ", Path)
 		return err
@@ -849,6 +939,6 @@
 			}
 		}
 	}
-	log.Errorw("invalid flow-info", log.Fields{"flow_info": FlowInfo})
+	log.Debugw("the flow can be related to a different service", log.Fields{"flow_info": FlowInfo})
 	return errors.New("invalid flow-info")
 }
diff --git a/adaptercore/resourcemanager/resourcemanager_test.go b/adaptercore/resourcemanager/resourcemanager_test.go
index 07448c6..cdce9ab 100644
--- a/adaptercore/resourcemanager/resourcemanager_test.go
+++ b/adaptercore/resourcemanager/resourcemanager_test.go
@@ -132,7 +132,7 @@
 			bands = append(bands, &ofp.OfpMeterBandHeader{Type: ofp.OfpMeterBandType_OFPMBT_DSCP_REMARK,
 				Rate: 1024, Data: &ofp.OfpMeterBandHeader_DscpRemark{DscpRemark: &ofp.OfpMeterBandDscpRemark{PrecLevel: 3}}})
 
-			sep := strings.Split(key, "/")[2]
+			sep := strings.Split(key, "/")[1]
 			val, _ := strconv.ParseInt(strings.Split(sep, ",")[1], 10, 32)
 			if uint32(val) > 1 {
 				meterConfig := &ofp.OfpMeterConfig{MeterId: uint32(val), Bands: bands}
@@ -410,15 +410,15 @@
 		name   string
 		fields *fields
 		args   args
-		want   uint32
+		want   []uint32
 	}{
-		{"GetCurrentAllocIDForOnu-1", getResMgr(), args{2, 2, 2}, 0},
+		{"GetCurrentAllocIDForOnu-1", getResMgr(), args{2, 2, 2}, []uint32{}},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			RsrcMgr := testResMgrObject(tt.fields)
-			if got := RsrcMgr.GetCurrentAllocIDForOnu(tt.args.intfID, tt.args.onuID, tt.args.uniID); got != tt.want {
-				t.Errorf("GetCurrentAllocIDForOnu() = %v, want %v", got, tt.want)
+			if got := RsrcMgr.GetCurrentAllocIDsForOnu(tt.args.intfID, tt.args.onuID, tt.args.uniID); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("GetCurrentAllocIDsForOnu() = %v, want %v", got, tt.want)
 			}
 		})
 	}
@@ -547,6 +547,7 @@
 		IntfID    uint32
 		OnuID     uint32
 		UniID     uint32
+		tpID      uint32
 	}
 	tests := []struct {
 		name    string
@@ -555,15 +556,15 @@
 		want    *ofp.OfpMeterConfig
 		wantErr error
 	}{
-		{"GetMeterIDOnu", getResMgr(), args{"DOWNSTREAM", 1, 1, 1},
+		{"GetMeterIDOnu", getResMgr(), args{"DOWNSTREAM", 1, 1, 1, 64},
 			&ofp.OfpMeterConfig{}, errors.New("failed to get Meter config from kvstore for path")},
-		{"GetMeterIDOnu", getResMgr(), args{"DOWNSTREAM", 2, 2, 2},
+		{"GetMeterIDOnu", getResMgr(), args{"DOWNSTREAM", 2, 2, 2, 65},
 			&ofp.OfpMeterConfig{}, errors.New("failed to get Meter config from kvstore for path")},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			RsrcMgr := testResMgrObject(tt.fields)
-			got, err := RsrcMgr.GetMeterIDForOnu(tt.args.Direction, tt.args.IntfID, tt.args.OnuID, tt.args.UniID)
+			got, err := RsrcMgr.GetMeterIDForOnu(tt.args.Direction, tt.args.IntfID, tt.args.OnuID, tt.args.UniID, tt.args.tpID)
 			if reflect.TypeOf(got) != reflect.TypeOf(tt.want) && err != nil {
 				t.Errorf("GetMeterIDForOnu() got = %v, want %v", got, tt.want)
 			}
@@ -606,10 +607,10 @@
 		name   string
 		fields *fields
 		args   args
-		want   uint32
+		want   []uint32
 	}{
 		{"GetTechProfileIDForOnu-1", getResMgr(), args{2, 2, 2},
-			uint32(1)},
+			[]uint32{1}},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
@@ -653,6 +654,7 @@
 		IntfID    uint32
 		OnuID     uint32
 		UniID     uint32
+		tpID      uint32
 	}
 	tests := []struct {
 		name    string
@@ -660,13 +662,14 @@
 		args    args
 		wantErr error
 	}{
-		{"RemoveMeterIdForOnu-1", getResMgr(), args{"DOWNSTREAM", 1, 1, 1},
+		{"RemoveMeterIdForOnu-1", getResMgr(), args{"DOWNSTREAM", 1, 1, 1, 64},
 			errors.New("failed to delete meter id %s from kvstore")},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			RsrcMgr := testResMgrObject(tt.fields)
-			if err := RsrcMgr.RemoveMeterIDForOnu(tt.args.Direction, tt.args.IntfID, tt.args.OnuID, tt.args.UniID); reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) && err != nil {
+			if err := RsrcMgr.RemoveMeterIDForOnu(tt.args.Direction, tt.args.IntfID, tt.args.OnuID, tt.args.UniID,
+				tt.args.tpID); reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) && err != nil {
 				t.Errorf("RemoveMeterIDForOnu() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})
@@ -678,6 +681,7 @@
 		IntfID uint32
 		OnuID  uint32
 		UniID  uint32
+		tpID   uint32
 	}
 	tests := []struct {
 		name    string
@@ -685,13 +689,14 @@
 		args    args
 		wantErr error
 	}{
-		{"RemoveTechProfileIDForOnu-1", getResMgr(), args{2, 2, 2},
+		{"RemoveTechProfileIDForOnu-1", getResMgr(), args{2, 2, 2, 64},
 			errors.New("failed to delete techprofile id resource %s in KV store")},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			RsrcMgr := testResMgrObject(tt.fields)
-			if err := RsrcMgr.RemoveTechProfileIDForOnu(tt.args.IntfID, tt.args.OnuID, tt.args.UniID); reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) && err != nil {
+			if err := RsrcMgr.RemoveTechProfileIDForOnu(tt.args.IntfID, tt.args.OnuID, tt.args.UniID,
+				tt.args.tpID); reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) && err != nil {
 				t.Errorf("RemoveTechProfileIDForOnu() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})
@@ -796,7 +801,8 @@
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			RsrcMgr := testResMgrObject(tt.fields)
-			if err := RsrcMgr.UpdateGEMportsPonportToOnuMapOnKVStore(tt.args.gemPorts, tt.args.PonPort, tt.args.onuID, tt.args.uniID); err != nil && reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) {
+			if err := RsrcMgr.UpdateGEMportsPonportToOnuMapOnKVStore(tt.args.gemPorts, tt.args.PonPort,
+				tt.args.onuID, tt.args.uniID); err != nil && reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) {
 				t.Errorf("UpdateGEMportsPonportToOnuMapOnKVStore() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})
@@ -809,6 +815,7 @@
 		IntfID      uint32
 		OnuID       uint32
 		UniID       uint32
+		tpID        uint32
 		MeterConfig *ofp.OfpMeterConfig
 	}
 	tests := []struct {
@@ -818,12 +825,13 @@
 		wantErr error
 	}{
 		{"UpdateMeterIDForOnu-1", getResMgr(), args{"DOWNSTREAM", 2, 2,
-			2, &ofp.OfpMeterConfig{}}, errors.New("failed to get Meter config from kvstore for path")},
+			2, 64, &ofp.OfpMeterConfig{}}, errors.New("failed to get Meter config from kvstore for path")},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			RsrcMgr := testResMgrObject(tt.fields)
-			if err := RsrcMgr.UpdateMeterIDForOnu(tt.args.Direction, tt.args.IntfID, tt.args.OnuID, tt.args.UniID, tt.args.MeterConfig); reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) && err != nil {
+			if err := RsrcMgr.UpdateMeterIDForOnu(tt.args.Direction, tt.args.IntfID, tt.args.OnuID, tt.args.UniID,
+				tt.args.tpID, tt.args.MeterConfig); reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) && err != nil {
 				t.Errorf("UpdateMeterIDForOnu() got = %v, want %v", err, tt.wantErr)
 			}
 		})