[VOL-3486] Generating unique DHCP TxId per service

Change-Id: I20b7d65ebe1d5ae7644aa0599571dc708e02e76f
diff --git a/internal/bbsim/devices/services.go b/internal/bbsim/devices/services.go
index 8aa3410..4b82e98 100644
--- a/internal/bbsim/devices/services.go
+++ b/internal/bbsim/devices/services.go
@@ -35,8 +35,8 @@
 
 // time to wait before fail EAPOL/DHCP
 // (it's a variable and not a constant so it can be overridden in the tests)
-var eapolWaitTime = 30 * time.Second
-var dhcpWaitTime = 30 * time.Second
+var eapolWaitTime = 60 * time.Second
+var dhcpWaitTime = 60 * time.Second
 
 type ServiceIf interface {
 	HandlePackets()      // start listening on the PacketCh
@@ -359,7 +359,7 @@
 		if msg.Type == packetHandlers.EAPOL {
 			eapol.HandleNextPacket(msg.OnuId, msg.IntfId, s.GemPort, s.Onu.Sn(), s.Onu.PortNo, s.EapolState, msg.Packet, s.Stream, nil)
 		} else if msg.Type == packetHandlers.DHCP {
-			_ = dhcp.HandleNextPacket(s.Onu.PonPort.Olt.ID, s.Onu.ID, s.Onu.PonPortID, s.Name, s.Onu.Sn(), s.Onu.PortNo, s.CTag, s.GemPort, s.HwAddress, s.DHCPState, msg.Packet, s.UsPonCTagPriority, s.Stream)
+			_ = dhcp.HandleNextPacket(s.Onu.ID, s.Onu.PonPortID, s.Name, s.Onu.Sn(), s.Onu.PortNo, s.CTag, s.GemPort, s.HwAddress, s.DHCPState, msg.Packet, s.UsPonCTagPriority, s.Stream)
 		} else if msg.Type == packetHandlers.IGMP {
 			log.Warn(hex.EncodeToString(msg.Packet.Data()))
 			_ = igmp.HandleNextPacket(s.Onu.PonPortID, s.Onu.ID, s.Onu.Sn(), s.Onu.PortNo, s.GemPort, s.HwAddress, msg.Packet, s.CTag, s.UsPonCTagPriority, s.Stream)
@@ -497,7 +497,7 @@
 		"GemPortId": s.GemPort,
 	}).Debugf("HandleDHCPStart")
 
-	if err := dhcp.SendDHCPDiscovery(s.Onu.PonPort.Olt.ID, s.Onu.PonPortID, s.Onu.ID, s.Name, int(s.CTag), s.GemPort,
+	if err := dhcp.SendDHCPDiscovery(s.Onu.PonPortID, s.Onu.ID, s.Name, int(s.CTag), s.GemPort,
 		s.Onu.Sn(), s.Onu.PortNo, s.DHCPState, s.HwAddress, s.UsPonCTagPriority, stream); err != nil {
 		serviceLogger.WithFields(log.Fields{
 			"OnuId":     s.Onu.ID,
diff --git a/internal/bbsim/responders/dhcp/dhcp.go b/internal/bbsim/responders/dhcp/dhcp.go
index 9b48c05..8ec3939 100644
--- a/internal/bbsim/responders/dhcp/dhcp.go
+++ b/internal/bbsim/responders/dhcp/dhcp.go
@@ -21,10 +21,6 @@
 	"encoding/hex"
 	"errors"
 	"fmt"
-	"net"
-	"reflect"
-	"strconv"
-
 	"github.com/google/gopacket"
 	"github.com/google/gopacket/layers"
 	"github.com/looplab/fsm"
@@ -32,6 +28,9 @@
 	bbsim "github.com/opencord/bbsim/internal/bbsim/types"
 	"github.com/opencord/voltha-protos/v3/go/openolt"
 	log "github.com/sirupsen/logrus"
+	"net"
+	"reflect"
+	"strconv"
 )
 
 var dhcpLogger = log.WithFields(log.Fields{
@@ -54,16 +53,25 @@
 	layers.DHCPOptNTPServers,
 }
 
-func createDefaultDHCPReq(oltId int, intfId uint32, onuId uint32, mac net.HardwareAddr) layers.DHCPv4 {
-	// NOTE we want to generate a unique XID, the easiest way is to concat the PON ID and the ONU ID
-	// we increment them by one otherwise:
-	// - OLT: 0 PON: 0 ONU: 62 = 062 -> 62
-	// - OLT: 0 PON: 6 ONU: 2 = 62 -> 62
-	xid, err := strconv.Atoi(fmt.Sprintf("%d%d%d", oltId+1, intfId+1, onuId+1))
+func macAddressToTxId(mac net.HardwareAddr) uint32 {
+
+	// NOTE we want to generate a unique XID,
+	// the easiest way is to transform the macAddress (already unique) into an integer
+	str := ""
+	for _, i := range mac {
+		str = str + fmt.Sprintf("%d", i)
+	}
+	xid, err := strconv.Atoi(str)
 	if err != nil {
 		log.Fatal("Can't generate unique XID for ONU")
 	}
 
+	return uint32(xid)
+}
+
+func createDefaultDHCPReq(mac net.HardwareAddr) layers.DHCPv4 {
+	xid := macAddressToTxId(mac)
+
 	return layers.DHCPv4{
 		Operation:    layers.DHCPOpRequest,
 		HardwareType: layers.LinkTypeEthernet,
@@ -96,8 +104,8 @@
 	return opts
 }
 
-func createDHCPDisc(oltId int, intfId uint32, onuId uint32, gemPort uint32, macAddress net.HardwareAddr) *layers.DHCPv4 {
-	dhcpLayer := createDefaultDHCPReq(oltId, intfId, onuId, macAddress)
+func createDHCPDisc(intfId uint32, onuId uint32, gemPort uint32, macAddress net.HardwareAddr) *layers.DHCPv4 {
+	dhcpLayer := createDefaultDHCPReq(macAddress)
 	defaultOpts := createDefaultOpts(intfId, onuId)
 	dhcpLayer.Options = append([]layers.DHCPOption{{
 		Type:   layers.DHCPOptMessageType,
@@ -116,8 +124,8 @@
 	return &dhcpLayer
 }
 
-func createDHCPReq(oltId int, intfId uint32, onuId uint32, macAddress net.HardwareAddr, offeredIp net.IP) *layers.DHCPv4 {
-	dhcpLayer := createDefaultDHCPReq(oltId, intfId, onuId, macAddress)
+func createDHCPReq(intfId uint32, onuId uint32, macAddress net.HardwareAddr, offeredIp net.IP) *layers.DHCPv4 {
+	dhcpLayer := createDefaultDHCPReq(macAddress)
 	defaultOpts := createDefaultOpts(intfId, onuId)
 
 	dhcpLayer.Options = append(defaultOpts, layers.DHCPOption{
@@ -265,10 +273,10 @@
 	return nil
 }
 
-func sendDHCPRequest(oltId int, ponPortId uint32, onuId uint32, serviceName string, serialNumber string, portNo uint32,
+func sendDHCPRequest(ponPortId uint32, onuId uint32, serviceName string, serialNumber string, portNo uint32,
 	cTag int, gemPortId uint32, onuStateMachine *fsm.FSM, onuHwAddress net.HardwareAddr,
 	offeredIp net.IP, pbit uint8, stream bbsim.Stream) error {
-	dhcp := createDHCPReq(oltId, ponPortId, onuId, onuHwAddress, offeredIp)
+	dhcp := createDHCPReq(ponPortId, onuId, onuHwAddress, offeredIp)
 	pkt, err := serializeDHCPPacket(ponPortId, onuId, cTag, onuHwAddress, dhcp, pbit)
 
 	if err != nil {
@@ -326,11 +334,11 @@
 	return nil
 }
 
-func SendDHCPDiscovery(oltId int, ponPortId uint32, onuId uint32, serviceName string, cTag int, gemPortId uint32,
+func SendDHCPDiscovery(ponPortId uint32, onuId uint32, serviceName string, cTag int, gemPortId uint32,
 	serialNumber string, portNo uint32, stateMachine *fsm.FSM, onuHwAddress net.HardwareAddr,
 	pbit uint8, stream bbsim.Stream) error {
 
-	dhcp := createDHCPDisc(oltId, ponPortId, onuId, gemPortId, onuHwAddress)
+	dhcp := createDHCPDisc(ponPortId, onuId, gemPortId, onuHwAddress)
 	pkt, err := serializeDHCPPacket(ponPortId, onuId, cTag, onuHwAddress, dhcp, pbit)
 
 	if err != nil {
@@ -385,7 +393,7 @@
 	return nil
 }
 
-func HandleNextPacket(oltId int, onuId uint32, ponPortId uint32, serviceName string, serialNumber string, portNo uint32,
+func HandleNextPacket(onuId uint32, ponPortId uint32, serviceName string, serialNumber string, portNo uint32,
 	cTag int, gemPortId uint32, onuHwAddress net.HardwareAddr, onuStateMachine *fsm.FSM,
 	pkt gopacket.Packet, pbit uint8, stream bbsim.Stream) error {
 
@@ -419,7 +427,7 @@
 	if dhcpLayer.Operation == layers.DHCPOpReply {
 		if dhcpMessageType == layers.DHCPMsgTypeOffer {
 			offeredIp := dhcpLayer.YourClientIP
-			if err := sendDHCPRequest(oltId, ponPortId, onuId, serviceName, serialNumber, portNo, cTag, gemPortId, onuStateMachine, onuHwAddress, offeredIp, pbit, stream); err != nil {
+			if err := sendDHCPRequest(ponPortId, onuId, serviceName, serialNumber, portNo, cTag, gemPortId, onuStateMachine, onuHwAddress, offeredIp, pbit, stream); err != nil {
 				dhcpLogger.WithFields(log.Fields{
 					"OnuId":       onuId,
 					"IntfId":      ponPortId,
diff --git a/internal/bbsim/responders/dhcp/dhcp_test.go b/internal/bbsim/responders/dhcp/dhcp_test.go
index 2a49836..bcb5c46 100644
--- a/internal/bbsim/responders/dhcp/dhcp_test.go
+++ b/internal/bbsim/responders/dhcp/dhcp_test.go
@@ -18,13 +18,14 @@
 
 import (
 	"errors"
+	"fmt"
 	"net"
 	"testing"
 
 	"github.com/looplab/fsm"
 	"github.com/opencord/voltha-protos/v3/go/openolt"
+	"github.com/stretchr/testify/assert"
 	"google.golang.org/grpc"
-	"gotest.tools/assert"
 )
 
 // MOCKS
@@ -58,13 +59,30 @@
 
 // TESTS
 
+func TestMacAddressToTxId(t *testing.T) {
+	mac1 := net.HardwareAddr{0x2e, 0x60, 0x00, 0x0c, 0x0f, 0x02}
+	mac2 := net.HardwareAddr{0x2e, 0x60, 0x00, 0x0f, 0x0c, 0x02}
+	mac3 := net.HardwareAddr{0x2e, 0x60, 0x00, 0x0c, 0x13, 0x01}
+
+	xid1 := macAddressToTxId(mac1)
+	xid2 := macAddressToTxId(mac2)
+	xid3 := macAddressToTxId(mac3)
+
+	fmt.Println(xid1)
+	fmt.Println(xid2)
+	fmt.Println(xid3)
+
+	assert.NotEqual(t, xid1, xid2)
+	assert.NotEqual(t, xid1, xid3)
+	assert.NotEqual(t, xid2, xid3)
+}
+
 func TestSendDHCPDiscovery(t *testing.T) {
 	dhcpStateMachine.SetState("dhcp_started")
 
 	var onuId uint32 = 1
 	var gemPortId uint32 = 1
 	var ponPortId uint32 = 0
-	var oltId int = 1
 	var serialNumber = "BBSM00000001"
 	var mac = net.HardwareAddr{0x2e, 0x60, 0x70, 0x13, byte(ponPortId), byte(onuId)}
 	var portNo uint32 = 16
@@ -74,7 +92,7 @@
 		fail:  false,
 	}
 
-	if err := SendDHCPDiscovery(oltId, ponPortId, onuId, "hsia", 900, gemPortId, serialNumber, portNo, dhcpStateMachine, mac, 7, stream); err != nil {
+	if err := SendDHCPDiscovery(ponPortId, onuId, "hsia", 900, gemPortId, serialNumber, portNo, dhcpStateMachine, mac, 7, stream); err != nil {
 		t.Errorf("SendDHCPDiscovery returned an error: %v", err)
 		t.Fail()
 	}