VOL-1624 Support for tech-profile creation on the first flow that references the tp-id (in write-metadata)

Getting meter from flow itself and bug fixes

Bug fix for dhcp packet-out

Change-Id: Ia466988bfdbfe49fd9a44729a4ba4a30fd991c54
diff --git a/adaptercore/resourcemanager/resourcemanager.go b/adaptercore/resourcemanager/resourcemanager.go
index b7d7737..dc5300a 100755
--- a/adaptercore/resourcemanager/resourcemanager.go
+++ b/adaptercore/resourcemanager/resourcemanager.go
@@ -28,6 +28,7 @@
 	ponrmgr "github.com/opencord/voltha-go/common/ponresourcemanager"
 	"github.com/opencord/voltha-go/db/kvstore"
 	"github.com/opencord/voltha-go/db/model"
+	ofp "github.com/opencord/voltha-protos/go/openflow_13"
 	"github.com/opencord/voltha-protos/go/openolt"
 )
 
@@ -37,6 +38,8 @@
 // BasePathKvStore - service/voltha/openolt/<device_id>
 const BasePathKvStore = "service/voltha/openolt/{%s}"
 
+const TP_ID_PATH_SUFFIX = "tp_id/{%d,%d,%d}"            // tp_id/<(pon_id, onu_id, uni_id)>
+const METER_ID_PATH_SUFFIX = "meter_id/{%d,%d,%d}/{%s}" // meter_id/<(pon_id, onu_id, uni_id)>/<direction>
 // FlowInfo holds the flow information
 type FlowInfo struct {
 	Flow            *openolt.Flow
@@ -58,7 +61,7 @@
 	ResourceMgrs map[uint32]*ponrmgr.PONResourceManager
 }
 
-func newKVClient(storeType, address string, timeout uint32) (kvstore.Client, error) {
+func newKVClient(storeType string, address string, timeout uint32) (kvstore.Client, error) {
 	log.Infow("kv-store-type", log.Fields{"store": storeType})
 	switch storeType {
 	case "consul":
@@ -413,8 +416,9 @@
 
 // GetFlowID return flow ID for a given pon interface id, onu id and uni id
 func (RsrcMgr *OpenOltResourceMgr) GetFlowID(ponIntfID uint32, ONUID uint32, uniID uint32,
+	gemportID uint32,
 	flowStoreCookie uint64,
-	flowCategory string) (uint32, error) {
+	flowCategory string, vlanPcp ...uint32) (uint32, error) {
 
 	var err error
 	FlowPath := fmt.Sprintf("%d,%d,%d", ponIntfID, ONUID, uniID)
@@ -425,13 +429,18 @@
 			FlowInfo := RsrcMgr.GetFlowIDInfo(ponIntfID, ONUID, uniID, uint32(flowID))
 			if FlowInfo != nil {
 				for _, Info := range *FlowInfo {
-					if flowCategory != "" && Info.FlowCategory == flowCategory {
-						log.Debug("Found flow matching with flow category", log.Fields{"flowId": flowID, "flowCategory": flowCategory})
-						return flowID, nil
+					if int32(gemportID) == Info.Flow.GemportId && flowCategory != "" && Info.FlowCategory == flowCategory {
+						log.Debug("Found flow matching with flow catagory", log.Fields{"flowId": flowID, "FlowCategory": flowCategory})
+						if Info.FlowCategory == "HSIA_FLOW" && Info.Flow.Classifier.OPbits == vlanPcp[0] {
+							log.Debug("Found matching vlan pcp ", log.Fields{"flowId": flowID, "Vlanpcp": vlanPcp[0]})
+							return flowID, nil
+						}
 					}
-					if flowStoreCookie != 0 && Info.FlowStoreCookie == flowStoreCookie {
-						log.Debug("Found flow matching with flowStore cookie", log.Fields{"flowId": flowID, "flowStoreCookie": flowStoreCookie})
-						return flowID, nil
+					if int32(gemportID) == Info.Flow.GemportId && flowStoreCookie != 0 && Info.FlowStoreCookie == flowStoreCookie {
+						if flowCategory != "" && Info.FlowCategory == flowCategory {
+							log.Debug("Found flow matching with flow catagory", log.Fields{"flowId": flowID, "FlowCategory": flowCategory})
+							return flowID, nil
+						}
 					}
 				}
 			}
@@ -694,3 +703,109 @@
 	}
 	return false
 }
+
+func (RMgr *OpenOltResourceMgr) GetTechProfileIdForOnu(IntfId uint32, OnuId uint32, UniId uint32) uint32 {
+	Path := fmt.Sprintf(TP_ID_PATH_SUFFIX, IntfId, OnuId, UniId)
+	var Data uint32
+	Value, err := RMgr.KVStore.Get(Path)
+	if err == nil {
+		if Value != nil {
+			Val, err := kvstore.ToByte(Value.Value)
+			if err != nil {
+				log.Errorw("Failed to convert into byte array", log.Fields{"error": err})
+				return Data
+			}
+			if err = json.Unmarshal(Val, &Data); err != nil {
+				log.Error("Failed to unmarshal", log.Fields{"error": err})
+				return Data
+			}
+		}
+	} else {
+		log.Errorf("Failed to get TP id from kvstore for path %s", Path)
+	}
+	log.Debugf("Getting TP id %d from path %s", Data, Path)
+	return Data
+
+}
+
+func (RMgr *OpenOltResourceMgr) RemoveTechProfileIdForOnu(IntfId uint32, OnuId uint32, UniId uint32) error {
+	IntfOnuUniId := fmt.Sprintf(TP_ID_PATH_SUFFIX, IntfId, OnuId, UniId)
+	if err := RMgr.KVStore.Delete(IntfOnuUniId); err != nil {
+		log.Error("Failed to delete techprofile id resource %s in KV store", IntfOnuUniId)
+		return err
+	}
+	return nil
+}
+
+func (RMgr *OpenOltResourceMgr) UpdateTechProfileIdForOnu(IntfId uint32, OnuId uint32,
+	UniId uint32, TpId uint32) error {
+	var Value []byte
+	var err error
+
+	IntfOnuUniId := fmt.Sprintf(TP_ID_PATH_SUFFIX, IntfId, OnuId, UniId)
+	log.Debugf("updating tp id %d on path %s", TpId, IntfOnuUniId)
+	Value, err = json.Marshal(TpId)
+	if err != nil {
+		log.Error("failed to Marshal")
+		return err
+	}
+	if err = RMgr.KVStore.Put(IntfOnuUniId, Value); err != nil {
+		log.Errorf("Failed to update resource %s", IntfOnuUniId)
+		return err
+	}
+	return err
+}
+
+func (RMgr *OpenOltResourceMgr) UpdateMeterIdForOnu(Direction string, IntfId uint32, OnuId uint32,
+	UniId uint32, MeterConfig *ofp.OfpMeterConfig) error {
+	var Value []byte
+	var err error
+
+	IntfOnuUniId := fmt.Sprintf(METER_ID_PATH_SUFFIX, IntfId, OnuId, UniId, Direction)
+	Value, err = json.Marshal(*MeterConfig)
+	if err != nil {
+		log.Error("failed to Marshal meter config")
+		return err
+	}
+	if err = RMgr.KVStore.Put(IntfOnuUniId, Value); err != nil {
+		log.Errorf("Failed to store meter into KV store %s", IntfOnuUniId)
+		return err
+	}
+	return err
+}
+
+func (RMgr *OpenOltResourceMgr) GetMeterIdForOnu(Direction string, IntfId uint32, OnuId uint32, UniId uint32) (*ofp.OfpMeterConfig, error) {
+	Path := fmt.Sprintf(METER_ID_PATH_SUFFIX, IntfId, OnuId, UniId, Direction)
+	var meterConfig ofp.OfpMeterConfig
+	Value, err := RMgr.KVStore.Get(Path)
+	if err == nil {
+		if Value != nil {
+			log.Debug("Found meter in KV store", log.Fields{"Direction": Direction})
+			Val, err := kvstore.ToByte(Value.Value)
+			if err != nil {
+				log.Errorw("Failed to convert into byte array", log.Fields{"error": err})
+				return nil, err
+			}
+			if err = json.Unmarshal(Val, &meterConfig); err != nil {
+				log.Error("Failed to unmarshal meterconfig", log.Fields{"error": err})
+				return nil, err
+			}
+		} else {
+			log.Debug("meter-does-not-exists-in-KVStore")
+			return nil, err
+		}
+	} else {
+		log.Errorf("Failed to get Meter config from kvstore for path %s", Path)
+
+	}
+	return &meterConfig, err
+}
+
+func (RMgr *OpenOltResourceMgr) RemoveMeterIdForOnu(Direction string, IntfId uint32, OnuId uint32, UniId uint32) error {
+	Path := fmt.Sprintf(METER_ID_PATH_SUFFIX, IntfId, OnuId, UniId, Direction)
+	if err := RMgr.KVStore.Delete(Path); err != nil {
+		log.Errorf("Failed to delete meter id %s from kvstore ", Path)
+		return err
+	}
+	return nil
+}