Add FTTB services example yaml and use sTag for FTTB DHCP packets

Change-Id: I2eb0d8d9f557afe0d6bb08741aa9b5486cc05f7c
diff --git a/VERSION b/VERSION
index f8f4f03..6b89d58 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.12.1
+1.12.2
diff --git a/configs/dt-fttb-services.yaml b/configs/dt-fttb-services.yaml
new file mode 100644
index 0000000..6ade030
--- /dev/null
+++ b/configs/dt-fttb-services.yaml
@@ -0,0 +1,35 @@
+# Contains a description of the services that needs to be created for each UNI and the corresponding tagging scheme
+
+# The service names used in this file are mandatory
+# for FTTB to work correctly.
+# DPU_MGMT_TRAFFIC is used in bbsim to detect when the sTag
+# must be used for DHCP packets instead of the cTag, and the
+# Olt app has custom behavior that is triggered by each of
+# these names.
+
+# DT FTTB
+workflow: dt-fttb
+  services:
+    - name: FTTB_SUBSCRIBER_TRAFFIC
+      c_tag: 101
+      c_tag_allocation: unique
+      s_tag: 3101
+      s_tag_allocation: unique
+      tp_id: 64
+    - name: DPU_ANCP_TRAFFIC
+      c_tag: 4
+      c_tag_allocation: shared
+      s_tag: 40
+      s_tag_allocation: shared
+      us_pon_s_tag_priority: 7
+      tp_id: 64
+    - name: DPU_MGMT_TRAFFIC
+      c_tag: 6
+      c_tag_allocation: shared
+      s_tag: 60
+      s_tag_allocation: shared
+      us_pon_c_tag_priority: 3
+      us_pon_s_tag_priority: 7
+      tp_id: 64
+      enable_mac_learning: true
+      needs_dhcp: true
\ No newline at end of file
diff --git a/internal/bbsim/devices/services.go b/internal/bbsim/devices/services.go
index 20abef6..3e4e83b 100644
--- a/internal/bbsim/devices/services.go
+++ b/internal/bbsim/devices/services.go
@@ -461,7 +461,14 @@
 		if msg.Type == packetHandlers.EAPOL {
 			eapol.HandleNextPacket(msg.OnuId, msg.IntfId, s.GemPort, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.Id, s.UniPort.Onu.PonPort.Olt.ID, s.EapolState, msg.Packet, s.Stream, nil)
 		} else if msg.Type == packetHandlers.DHCP {
-			_ = dhcp.HandleNextPacket(s.UniPort.Onu.ID, s.UniPort.Onu.PonPortID, s.Name, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.CTag, s.GemPort, s.UniPort.ID, s.HwAddress, s.DHCPState, msg.Packet, s.UsPonCTagPriority, s.Stream)
+			tag := int(s.CTag)
+			priority := s.UsPonCTagPriority
+			if s.Name == fttbDpuMgmtServiceName {
+				tag = int(s.STag)
+				priority = s.UsPonSTagPriority
+			}
+
+			_ = dhcp.HandleNextPacket(s.UniPort.Onu.ID, s.UniPort.Onu.PonPortID, s.Name, s.UniPort.Onu.Sn(), s.UniPort.PortNo, tag, s.GemPort, s.UniPort.ID, s.HwAddress, s.DHCPState, msg.Packet, priority, s.Stream)
 		} else if msg.Type == packetHandlers.IGMP {
 			log.Warn(hex.EncodeToString(msg.Packet.Data()))
 			_ = igmp.HandleNextPacket(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.GemPort, s.HwAddress, msg.Packet, s.CTag, s.UsPonCTagPriority, s.Stream)
@@ -630,8 +637,15 @@
 		"UniId":     s.UniPort.ID,
 	}).Debugf("HandleDHCPStart")
 
-	if err := dhcp.SendDHCPDiscovery(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.Name, int(s.CTag), s.GemPort,
-		s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.DHCPState, s.HwAddress, s.UsPonCTagPriority, stream); err != nil {
+	tag := int(s.CTag)
+	priority := s.UsPonCTagPriority
+	if s.Name == fttbDpuMgmtServiceName {
+		tag = int(s.STag)
+		priority = s.UsPonSTagPriority
+	}
+
+	if err := dhcp.SendDHCPDiscovery(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.Name, tag, s.GemPort,
+		s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.DHCPState, s.HwAddress, priority, stream); err != nil {
 		serviceLogger.WithFields(log.Fields{
 			"OnuId":     s.UniPort.Onu.ID,
 			"IntfId":    s.UniPort.Onu.PonPortID,
diff --git a/internal/bbsim/responders/dhcp/dhcp.go b/internal/bbsim/responders/dhcp/dhcp.go
index 8adb65e..7fc7b3c 100644
--- a/internal/bbsim/responders/dhcp/dhcp.go
+++ b/internal/bbsim/responders/dhcp/dhcp.go
@@ -21,6 +21,10 @@
 	"encoding/hex"
 	"errors"
 	"fmt"
+	"net"
+	"reflect"
+	"strconv"
+
 	"github.com/google/gopacket"
 	"github.com/google/gopacket/layers"
 	"github.com/looplab/fsm"
@@ -28,9 +32,6 @@
 	bbsim "github.com/opencord/bbsim/internal/bbsim/types"
 	"github.com/opencord/voltha-protos/v5/go/openolt"
 	log "github.com/sirupsen/logrus"
-	"net"
-	"reflect"
-	"strconv"
 )
 
 var dhcpLogger = log.WithFields(log.Fields{
@@ -158,7 +159,7 @@
 	return &dhcpLayer
 }
 
-func serializeDHCPPacket(cTag int, srcMac net.HardwareAddr, dhcp *layers.DHCPv4, pbit uint8) (gopacket.Packet, error) {
+func serializeDHCPPacket(tag int, srcMac net.HardwareAddr, dhcp *layers.DHCPv4, pbit uint8) (gopacket.Packet, error) {
 	buffer := gopacket.NewSerializeBuffer()
 
 	options := gopacket.SerializeOptions{
@@ -194,7 +195,7 @@
 
 	untaggedPkt := gopacket.NewPacket(buffer.Bytes(), layers.LayerTypeEthernet, gopacket.Default)
 
-	taggedPkt, err := packetHandlers.PushSingleTag(cTag, untaggedPkt, pbit)
+	taggedPkt, err := packetHandlers.PushSingleTag(tag, untaggedPkt, pbit)
 	if err != nil {
 		dhcpLogger.Error("TagPacket")
 		return nil, err
@@ -279,10 +280,10 @@
 }
 
 func sendDHCPRequest(ponPortId uint32, onuId uint32, serviceName string, serialNumber string, portNo uint32,
-	cTag int, gemPortId uint32, onuStateMachine *fsm.FSM, onuHwAddress net.HardwareAddr,
+	tag int, gemPortId uint32, onuStateMachine *fsm.FSM, onuHwAddress net.HardwareAddr,
 	offeredIp net.IP, pbit uint8, uniId uint32, stream bbsim.Stream) error {
 	dhcp := createDHCPReq(ponPortId, onuId, onuHwAddress, offeredIp, gemPortId)
-	pkt, err := serializeDHCPPacket(cTag, onuHwAddress, dhcp, pbit)
+	pkt, err := serializeDHCPPacket(tag, onuHwAddress, dhcp, pbit)
 
 	if err != nil {
 		dhcpLogger.WithFields(log.Fields{
@@ -296,8 +297,6 @@
 		}
 		return err
 	}
-	// NOTE I don't think we need to tag the packet
-	//taggedPkt, err := packetHandlers.PushSingleTag(cTag, pkt)
 
 	msg := bbsim.ByteMsg{
 		IntfId: ponPortId,
@@ -339,12 +338,12 @@
 	return nil
 }
 
-func SendDHCPDiscovery(ponPortId uint32, onuId uint32, serviceName string, cTag int, gemPortId uint32,
+func SendDHCPDiscovery(ponPortId uint32, onuId uint32, serviceName string, tag int, gemPortId uint32,
 	serialNumber string, portNo uint32, uniId uint32, stateMachine *fsm.FSM, onuHwAddress net.HardwareAddr,
 	pbit uint8, stream bbsim.Stream) error {
 
 	dhcp := createDHCPDisc(ponPortId, onuId, gemPortId, onuHwAddress)
-	pkt, err := serializeDHCPPacket(cTag, onuHwAddress, dhcp, pbit)
+	pkt, err := serializeDHCPPacket(tag, onuHwAddress, dhcp, pbit)
 
 	if err != nil {
 		dhcpLogger.WithFields(log.Fields{
@@ -361,8 +360,6 @@
 		}
 		return err
 	}
-	// NOTE I don't think we need to tag the packet
-	//taggedPkt, err := packetHandlers.PushSingleTag(cTag, pkt)
 
 	msg := bbsim.ByteMsg{
 		IntfId: ponPortId,
@@ -411,7 +408,7 @@
 }
 
 func HandleNextPacket(onuId uint32, ponPortId uint32, serviceName string, serialNumber string, portNo uint32,
-	cTag int, gemPortId uint32, uniId uint32, onuHwAddress net.HardwareAddr, onuStateMachine *fsm.FSM,
+	tag int, gemPortId uint32, uniId uint32, onuHwAddress net.HardwareAddr, onuStateMachine *fsm.FSM,
 	pkt gopacket.Packet, pbit uint8, stream bbsim.Stream) error {
 
 	dhcpLayer, err := GetDhcpLayer(pkt)
@@ -450,7 +447,7 @@
 	if dhcpLayer.Operation == layers.DHCPOpReply {
 		if dhcpMessageType == layers.DHCPMsgTypeOffer {
 			offeredIp := dhcpLayer.YourClientIP
-			if err := sendDHCPRequest(ponPortId, onuId, serviceName, serialNumber, portNo, cTag, gemPortId, onuStateMachine, onuHwAddress, offeredIp, pbit, uniId, stream); err != nil {
+			if err := sendDHCPRequest(ponPortId, onuId, serviceName, serialNumber, portNo, tag, gemPortId, onuStateMachine, onuHwAddress, offeredIp, pbit, uniId, stream); err != nil {
 				dhcpLogger.WithFields(log.Fields{
 					"OnuId":       onuId,
 					"IntfId":      ponPortId,