VOL-2419: Add DHCP and HSIA flow add support for ATT worflow
VOL-2422: Integrate DT workflow with HSIA flow add support

Change-Id: Id77fbf6adecea759a0ef982399c30b4a4b88593b
diff --git a/core/utils.go b/core/utils.go
index 01ff500..a99096e 100644
--- a/core/utils.go
+++ b/core/utils.go
@@ -18,15 +18,25 @@
 
 import (
 	"fmt"
+
 	"github.com/opencord/voltha-lib-go/v2/pkg/log"
 	"github.com/opencord/voltha-protos/v2/go/openolt"
 )
 
+type DtStagKey struct {
+	ponIntf, onuID, uniID uint32
+}
+
+var currDtStag uint32
+var DtStag map[DtStagKey]uint32
+var DtCtag map[uint32]uint32
 var AttCtag map[uint32]uint32
 
 func init() {
 	_, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
 	AttCtag = make(map[uint32]uint32)
+	DtCtag = make(map[uint32]uint32)
+	DtStag = make(map[DtStagKey]uint32)
 }
 
 const (
@@ -75,26 +85,55 @@
 	return AttCtag[ponIntf]
 }
 
+func GetDtCtag(ponIntf uint32) uint32 {
+	var currCtag uint32
+	var ok bool
+	if currCtag, ok = DtCtag[ponIntf]; !ok {
+		// Start with ctag 1
+		DtCtag[ponIntf] = 1
+		return DtCtag[ponIntf]
+	}
+	DtCtag[ponIntf] = currCtag + 1
+	return DtCtag[ponIntf]
+}
+
 func GetAttStag(ponIntf uint32) uint32 {
 	// start with stag 2
 	return ponIntf + 2
 }
 
+func GetDtStag(ponIntf uint32, onuID uint32, uniID uint32) uint32 {
+	// Dt workflow requires unique stag for each subscriber
+	key := DtStagKey{ponIntf: ponIntf, onuID: onuID, uniID: uniID}
+
+	if value, ok := DtStag[key]; ok {
+		return value
+	} else {
+		DtStag[key] = currDtStag + 1
+		currDtStag = DtStag[key]
+	}
+	return DtStag[key]
+}
+
 // TODO: More workflow support to be added here
 func GetCtag(workFlowName string, ponIntf uint32) uint32 {
 	switch workFlowName {
 	case "ATT":
 		return GetAttCtag(ponIntf)
+	case "DT":
+		return GetDtCtag(ponIntf)
 	default:
 		log.Errorw("unknown-workflowname", log.Fields{"workflow": workFlowName})
 	}
 	return 0
 }
 
-func GetStag(workFlowName string, ponIntf uint32) uint32 {
+func GetStag(workFlowName string, ponIntf uint32, onuID uint32, uniID uint32) uint32 {
 	switch workFlowName {
 	case "ATT":
 		return GetAttStag(ponIntf)
+	case "DT":
+		return GetDtStag(ponIntf, onuID, uniID)
 	default:
 		log.Errorw("unknown-workflowname", log.Fields{"workflow": workFlowName})
 	}