/*
* Copyright 2022-present Open Networking Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
 */

package application

import (
	"context"
	"encoding/hex"
	"errors"
	"net"
	"sync"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"

	cntlr "voltha-go-controller/internal/pkg/controller"
	"voltha-go-controller/internal/pkg/of"
	"voltha-go-controller/internal/pkg/util"
	"voltha-go-controller/log"
)

// DhcpRelayState type
type DhcpRelayState uint8

const (
	// DhcpRelayStateNone constant
	DhcpRelayStateNone DhcpRelayState = iota
	// DhcpRelayStateDiscover constant
	DhcpRelayStateDiscover
	// DhcpRelayStateOffer constant
	DhcpRelayStateOffer
	// DhcpRelayStateRequest constant
	DhcpRelayStateRequest
	// DhcpRelayStateAck constant
	DhcpRelayStateAck
	// DhcpRelayStateNAK constant
	DhcpRelayStateNAK
	// DhcpRelayStateRelease constant
	DhcpRelayStateRelease
)

// RemoteIDType represents data type for various RemoteID types
type RemoteIDType string

// List of RemoteID types supported
const (
	MACAddress      RemoteIDType = "MAC_ADDRESS"
	CustomRemotedID RemoteIDType = "Custom"
)

// MaxLenDhcpv6DUID constant
const MaxLenDhcpv6DUID = 130 // 2: DUID-Type, 128: MaxLen of DUID value

// opt82 constant
const opt82 = 82

// Dhcpv6RelayState type
type Dhcpv6RelayState uint8

const (
	// Dhcpv6RelayStateNone constant
	Dhcpv6RelayStateNone Dhcpv6RelayState = iota
	// Dhcpv6RelayStateSolicit constant
	Dhcpv6RelayStateSolicit
	// Dhcpv6RelayStateReply constant
	Dhcpv6RelayStateReply
	// Dhcpv6RelayStateRelease constant
	Dhcpv6RelayStateRelease
)

var (
	// ErrSessionDoNotExist error type
	ErrSessionDoNotExist = errors.New("Session Doesn't Exist")
)

// IDhcpRelaySession to get dhcp session field value
type IDhcpRelaySession interface {
	GetCircuitID() []byte
	GetRemoteID() []byte
	GetNniVlans() (uint16, uint16)
	GetDhcpState() DhcpRelayState
	GetDhcpv6State() Dhcpv6RelayState
	SetDhcpState(DhcpRelayState)
	SetDhcpv6State(Dhcpv6RelayState)
	SetMacAddr(context.Context, net.HardwareAddr)
	DhcpResultInd(context.Context, *layers.DHCPv4)
	Dhcpv6ResultInd(cntx context.Context, ipv6Addr net.IP, leaseTime uint32)
}

// DhcpRelayVnet : The DHCP relay sessions are stored in a map to be retrieved from when
// a response is received from the network. The map uses the VLANs and the
// the MAC address as key to finding the service
// DHCP Relay Virtual Network hosts a set of DHCP relay sessions that belong
// to the network. It supports two VLANs as its identify. If a single VLAN or
// no VLAN is to be used, those two should be passed as 4096 (VlanNone)
type DhcpRelayVnet struct {
	sessions    map[[6]byte]IDhcpRelaySession
	sessionsv6  map[[MaxLenDhcpv6DUID]byte]IDhcpRelaySession
	sessionLock sync.RWMutex
	OuterVlan   uint16
	InnerVlan   uint16
}

// DhcpNetworks hosts different DHCP networks that in turn hold the DHCP
// sessions
type DhcpNetworks struct {
	Networks map[uint32]*DhcpRelayVnet
}

func init() {
	RegisterPacketHandler(DHCPv4, ProcessUDP4Packet)
	RegisterPacketHandler(DHCPv6, ProcessUDP6Packet)
}

// NewDhcpRelayVnet is constructor for a DHCP Relay Virtual network
func NewDhcpRelayVnet(outerVlan uint16, innerVlan uint16) *DhcpRelayVnet {
	var drv DhcpRelayVnet

	drv.OuterVlan = outerVlan
	drv.InnerVlan = innerVlan
	drv.sessions = make(map[[6]byte]IDhcpRelaySession)
	drv.sessionsv6 = make(map[[MaxLenDhcpv6DUID]byte]IDhcpRelaySession)
	return &drv
}

// GetDhcpVnet to add dhcp vnet
func (dn *DhcpNetworks) GetDhcpVnet(outerVlan uint16, innerVlan uint16) *DhcpRelayVnet {
	comboVlan := uint32(outerVlan)<<16 + uint32(innerVlan)
	drv, ok := dn.Networks[comboVlan]
	if ok {
		return drv
	}
	return nil
}

// AddDhcpVnet to add dhcp vnet
func (dn *DhcpNetworks) AddDhcpVnet(outerVlan uint16, innerVlan uint16) *DhcpRelayVnet {
	comboVlan := uint32(outerVlan)<<16 + uint32(innerVlan)
	if drv, ok := dn.Networks[comboVlan]; ok {
		return drv
	}
	drv := NewDhcpRelayVnet(outerVlan, innerVlan)
	dn.Networks[comboVlan] = drv
	return drv
}

// NewDhcpNetworks to get new dhcp network
func NewDhcpNetworks() *DhcpNetworks {
	var dn DhcpNetworks
	dn.Networks = make(map[uint32]*DhcpRelayVnet)
	return &dn
}

// AddDhcpSession to add dhcp session
func (dn *DhcpNetworks) AddDhcpSession(pkt gopacket.Packet, session IDhcpRelaySession) error {
	var key [6]byte
	ethl := pkt.Layer(layers.LayerTypeEthernet)
	eth, _ := ethl.(*layers.Ethernet)
	addr := eth.SrcMAC
	if len(addr) != 6 {
		logger.Errorw(ctx, "Invalid MAC address", log.Fields{"Addr": addr})
		return errors.New("Invalid MAC address")
	}
	copy(key[:], addr[0:6])

	drv := dn.AddDhcpVnet(session.GetNniVlans())

	drv.sessionLock.Lock()
	drv.sessions[key] = session
	drv.sessionLock.Unlock()
	return nil
}

// DelDhcpSession to delete dhcp session
func (dn *DhcpNetworks) DelDhcpSession(pkt gopacket.Packet, session IDhcpRelaySession) {
	var key [6]byte
	ethl := pkt.Layer(layers.LayerTypeEthernet)
	eth, _ := ethl.(*layers.Ethernet)
	addr := eth.SrcMAC
	if len(addr) != 6 {
		logger.Errorw(ctx, "Invalid MAC address", log.Fields{"Addr": addr})
		return
	}
	copy(key[:], addr[0:6])
	drv := dn.AddDhcpVnet(session.GetNniVlans())
	drv.sessionLock.Lock()
	delete(drv.sessions, key)
	drv.sessionLock.Unlock()
}

// delDhcpSessions to delete dhcp sessions
func delDhcpSessions(addr net.HardwareAddr, outervlan of.VlanType, innervlan of.VlanType, sessionKey [MaxLenDhcpv6DUID]byte) {
	var key [6]byte
	if addr == nil || !NonZeroMacAddress(addr) {
		logger.Warnw(ctx, "Invalid MAC address", log.Fields{"Addr": addr})
		return
	}
	copy(key[:], addr[0:6])
	drv := dhcpNws.AddDhcpVnet(uint16(outervlan), uint16(innervlan))
	drv.sessionLock.Lock()
	delete(drv.sessions, key)
	delete(drv.sessionsv6, sessionKey)
	drv.sessionLock.Unlock()
	logger.Infow(ctx, "DHCP Sessions deleted", log.Fields{"MAC": addr})
}

// AddDhcp6Session to add dhcpv6 session
func (dn *DhcpNetworks) AddDhcp6Session(key [MaxLenDhcpv6DUID]byte, session IDhcpRelaySession) error {
	outerVlan, innerVlan := session.GetNniVlans()
	logger.Infow(ctx, "Adding Session", log.Fields{"outerVlan": outerVlan, "innerVlan": innerVlan, "Addr": key})
	drv := dn.AddDhcpVnet(outerVlan, innerVlan)
	drv.sessionLock.Lock()
	drv.sessionsv6[key] = session
	drv.sessionLock.Unlock()
	return nil
}

// DelDhcp6Session to delete dhcpv6 session
func (dn *DhcpNetworks) DelDhcp6Session(key [MaxLenDhcpv6DUID]byte, session IDhcpRelaySession) {
	outerVlan, innerVlan := session.GetNniVlans()
	logger.Infow(ctx, "Get Session", log.Fields{"OuterVLAN": outerVlan, "InnerVLAN": innerVlan, "Addr": key})
	drv := dn.GetDhcpVnet(outerVlan, innerVlan)
	drv.sessionLock.Lock()
	delete(drv.sessionsv6, key)
	drv.sessionLock.Unlock()
}

// GetDhcpSession to get dhcp session info
func (dn *DhcpNetworks) GetDhcpSession(outerVlan uint16, innerVlan uint16, addr net.HardwareAddr) (IDhcpRelaySession, error) {
	var key [6]byte
	if len(addr) != 6 {
		logger.Errorw(ctx, "Invalid MAC address", log.Fields{"Addr": addr})
		return nil, errors.New("Invalid MAC address")
	}
	copy(key[:], addr[0:6])
	drv := dn.AddDhcpVnet(outerVlan, innerVlan)
	drv.sessionLock.RLock()
	defer drv.sessionLock.RUnlock()
	if session, ok := drv.sessions[key]; ok {
		return session, nil
	}
	return nil, ErrSessionDoNotExist
}

// GetDhcp6Session to get Dhcp6Session
func (dn *DhcpNetworks) GetDhcp6Session(outerVlan uint16, innerVlan uint16, key [MaxLenDhcpv6DUID]byte) (IDhcpRelaySession, error) {
	logger.Infow(ctx, "Locating Session", log.Fields{"OuterVlan": outerVlan, "InnerVlan": innerVlan, "key": key})

	drv := dn.AddDhcpVnet(outerVlan, innerVlan)
	drv.sessionLock.RLock()
	defer drv.sessionLock.RUnlock()
	if session, ok := drv.sessionsv6[key]; ok {
		return session, nil
	}
	return nil, ErrSessionDoNotExist
}

// GetVlansFromPacket to get vlans from the packet
func GetVlansFromPacket(pkt gopacket.Packet) (innerVlan of.VlanType, outerVlan of.VlanType) {
	vlans := GetVlans(pkt)
	if len(vlans) == 1 {
		outerVlan = vlans[0]
		innerVlan = of.VlanNone
	} else if len(vlans) == 0 {
		innerVlan = of.VlanNone
		outerVlan = of.VlanNone
	} else {
		innerVlan = vlans[1]
		outerVlan = vlans[0]
	}
	return
}

// GetVnetForV4Nni to get vnet for v4 Nni
func GetVnetForV4Nni(dhcp *layers.DHCPv4, cvlan of.VlanType, svlan of.VlanType, pbit uint8) ([]*VoltPortVnet, error) {
	var err error
	var session IDhcpRelaySession
	var vpvList []*VoltPortVnet
	logger.Infow(ctx, "Mac Obtained MAC: ", log.Fields{"Addr": dhcp.ClientHWAddr})
	session, err = dhcpNws.GetDhcpSession(uint16(svlan), uint16(cvlan), dhcp.ClientHWAddr)

	if session != nil {
		vpv, ok := session.(*VoltPortVnet)
		logger.Infow(ctx, "Session Exist: VPV found", log.Fields{"VPV": vpv})
		if ok {
			vpvList = append(vpvList, vpv)
			return vpvList, nil
		}
	}

	if err == ErrSessionDoNotExist {
		//No DHCP Session found, find matching VPV to send the packet out
		logger.Info(ctx, "Session Doesnt Exist: Finding matching VPV")
		return GetApplication().GetVpvsForDsPkt(cvlan, svlan, dhcp.ClientHWAddr, pbit)
	}
	return nil, errors.New("The session retrieved of wrong type")
}

// GetVnetForV6Nni to get vnet for v6 Nni
func GetVnetForV6Nni(dhcp *layers.DHCPv6, cvlan of.VlanType, svlan of.VlanType,
	pbit uint8, clientMAC net.HardwareAddr) ([]*VoltPortVnet, net.HardwareAddr, error) {
	var err error
	var session IDhcpRelaySession
	var vpvList []*VoltPortVnet

	var sessionKey [MaxLenDhcpv6DUID]byte

	clientDuid, decodedDuid := getDhcpv6ClientDUID(dhcp)
	if clientDuid == nil || decodedDuid == nil {
		copy(sessionKey[:], clientMAC)
	} else {
		copy(sessionKey[:], clientDuid[0:])
		if decodedDuid.Type == layers.DHCPv6DUIDTypeLLT || decodedDuid.Type == layers.DHCPv6DUIDTypeLL {
			clientMAC = decodedDuid.LinkLayerAddress
		}
	}
	session, err = dhcpNws.GetDhcp6Session(uint16(svlan), uint16(cvlan), sessionKey)
	if session != nil {
		vpv, ok := session.(*VoltPortVnet)
		logger.Infow(ctx, "Session Exist: VPV found", log.Fields{"VPV": vpv})
		if ok {
			vpvList = append(vpvList, vpv)
			return vpvList, clientMAC, nil
		}
	}

	if err == ErrSessionDoNotExist {
		//No DHCP Session found, find matching VPV to send the packet out
		logger.Info(ctx, "Session Doesnt Exist: Finding matching VPV")
		vpvList, err := GetApplication().GetVpvsForDsPkt(cvlan, svlan, clientMAC, pbit)
		return vpvList, clientMAC, err
	}
	return nil, clientMAC, errors.New("The session retrieved of wrong type")
}

/*
// getDhcpv4ClientMacAddr to get mac address for dhcpv4 client
func getDhcpv4ClientMacAddr(pkt gopacket.Packet) net.HardwareAddr {
	dhcp := pkt.Layer(layers.LayerTypeDHCPv4).(*layers.DHCPv4)
	logger.Infow(ctx, "Mac Obtained v4: ", log.Fields{"Addr": dhcp.ClientHWAddr})
	return dhcp.ClientHWAddr
}

// getDhcpv6ClientMacAddr to get mac address for dhcpv6 client
func getDhcpv6ClientMacAddr(dhcpv6 *layers.DHCPv6) net.HardwareAddr {
	var cID layers.DHCPv6Option
	for _, option := range dhcpv6.Options {
		if option.Code == layers.DHCPv6OptClientID {
			cID = option
		}
	}
	duid := &layers.DHCPv6DUID{}

	//If cID is not found, DecodeFromBytes() returns error on empty cID
	if err := duid.DecodeFromBytes(cID.Data); err == nil {
		logger.Infow(ctx, "Mac Obtained v6: ", log.Fields{"Addr": duid.LinkLayerAddress, "Option": cID.String()})
		return duid.LinkLayerAddress
	}
	return nil
}*/

// getDhcpv6ClientDUID to get Dhcpv6 client DUID
func getDhcpv6ClientDUID(dhcpv6 *layers.DHCPv6) ([]byte, *layers.DHCPv6DUID) {
	for _, option := range dhcpv6.Options {
		logger.Debugw(ctx, "DHCPv6 Options", log.Fields{"option": option.Code})
		if option.Code == layers.DHCPv6OptClientID {
			duid := &layers.DHCPv6DUID{}
			err := duid.DecodeFromBytes(option.Data)
			if err == nil {
				logger.Infow(ctx, "ClientIdentifier", log.Fields{"DUID": duid, "Option": option.String()})
				duidLen := len(option.Data)
				if duidLen > 130 {
					duidLen = 130
				}
				return option.Data[0:duidLen], duid
			}
			logger.Errorw(ctx, "Client DUID decode failed", log.Fields{"error": err})
			break
		}
	}
	logger.Error(ctx, "Client DUID is not present in the packet")
	return nil, nil
}

// AddDhcpv4Option82 : DHCPv4 packet operations
// Addition of DHCP Option 82 which codes circuit-id and remote-id
// into the packet. This happens as the request is relayed to the
// DHCP servers on the NNI
func AddDhcpv4Option82(svc *VoltService, rID []byte, dhcpv4 *layers.DHCPv4) {
	//NOTE : both cID and rID should not be empty if this function is called
	cID := svc.GetCircuitID()
	var data []byte
	if len(cID) != 0 {
		data = append(data, 0x01)
		data = append(data, byte(len(cID)))
		data = append(data, cID...)
	}
	if len(rID) != 0 {
		data = append(data, 0x02)
		data = append(data, byte(len(rID)))
		data = append(data, rID...)
	}

	if svc.isDataRateAttrPresent() {
		minDrUs := util.Uint32ToByte(svc.MinDataRateUs)
		data = append(data, TYPEMINDATAUS)
		data = append(data, byte(len(minDrUs)))
		data = append(data, minDrUs...)

		minDrDs := util.Uint32ToByte(svc.MinDataRateDs)
		data = append(data, TYPEMINDATADS)
		data = append(data, byte(len(minDrDs)))
		data = append(data, minDrDs...)

		maxDrUs := util.Uint32ToByte(svc.MaxDataRateUs)
		data = append(data, TYPEMAXDATAUS)
		data = append(data, byte(len(maxDrUs)))
		data = append(data, maxDrUs...)

		maxDrDs := util.Uint32ToByte(svc.MaxDataRateDs)
		data = append(data, TYPEMAXDATADS)
		data = append(data, byte(len(maxDrDs)))
		data = append(data, maxDrDs...)
	}

	option := layers.NewDHCPOption(82, data)
	dhcpv4.Options = append(dhcpv4.Options, option)
}

// DelOption82 : Deletion of option 82 from the packet received on the NNI interface.
// Once the packet is received, the option 82 is stripped off and the
// packet is forwarded towards access
func DelOption82(dhcpv4 *layers.DHCPv4) {
	for index, option := range dhcpv4.Options {
		if option.Type == opt82 {
			dhcpv4.Options = append(dhcpv4.Options[0:index], dhcpv4.Options[index+1:]...)
			return
		}
	}
}

// DhcpMsgType returns the DHCP message type from the packet
func DhcpMsgType(dhcp *layers.DHCPv4) layers.DHCPMsgType {
	for _, option := range dhcp.Options {
		if option.Type == layers.DHCPOptMessageType {
			return layers.DHCPMsgType(option.Data[0])
		}
	}
	return layers.DHCPMsgTypeUnspecified
}

// GetIpv4Addr returns the IP address in the DHCP reply
func GetIpv4Addr(dhcp *layers.DHCPv4) (net.IP, int64) {
	var leaseTime uint32
	for _, opt := range dhcp.Options {
		if opt.Type == layers.DHCPOptLeaseTime {
			leaseTime = GetIPv4LeaseTime(opt)
		}
	}
	return dhcp.YourClientIP, int64(leaseTime)
}

// GetIPv4LeaseTime get ip lease time
func GetIPv4LeaseTime(opt layers.DHCPOption) uint32 {
	return uint32(opt.Data[0])<<24 | uint32(opt.Data[1])<<16 | uint32(opt.Data[2])<<8 | uint32(opt.Data[3])
}

// GetIpv6Addr returns the IPv6 address in the DHCPv6 reply
func GetIpv6Addr(dhcp6 *layers.DHCPv6) (net.IP, uint32) {
	var ipv6Addr net.IP
	var leaseTime uint32

	//Check for IANA allocation, if not present, then look for IAPD allocation
	if dhcp6.MsgType == layers.DHCPv6MsgTypeReply {
		ipv6Addr, leaseTime = GetIANAAddress(dhcp6)
		if ipv6Addr == nil {
			ipv6Addr, leaseTime = GetIAPDAddress(dhcp6)
		}
	}
	return ipv6Addr, leaseTime
}

// GetIANAAddress returns the IPv6 address in the DHCPv6 reply
func GetIANAAddress(dhcp6 *layers.DHCPv6) (net.IP, uint32) {
	var ipv6Addr net.IP
	var leaseTime uint32
	if dhcp6.MsgType == layers.DHCPv6MsgTypeReply {
		for _, o := range dhcp6.Options {
			if o.Code == layers.DHCPv6OptIANA {
				iana := &layers.DHCPv6IANA{}
				err := iana.DecodeFromBytes(o.Data)
				if err == nil {
					ipv6Addr = iana.IA.IPv6Addr
					leaseTime = iana.IA.ValidLifeTime
					logger.Debugw(ctx, "IPv6 Allocated", log.Fields{"IANA IPv6": ipv6Addr})
					return ipv6Addr, leaseTime
				}
				logger.Warnw(ctx, "Decode of IANA Failed", log.Fields{"Reason": err.Error()})
				break
			}
		}
	}
	return nil, 0
}

// GetIAPDAddress returns the IPv6 address in the DHCPv6 reply
func GetIAPDAddress(dhcp6 *layers.DHCPv6) (net.IP, uint32) {
	var ipv6Addr net.IP
	var leaseTime uint32
	if dhcp6.MsgType == layers.DHCPv6MsgTypeReply {
		for _, o := range dhcp6.Options {
			if o.Code == layers.DHCPv6OptIAPD {
				iapd := &layers.DHCPv6IAPD{}
				if err := iapd.DecodeFromBytes(o.Data); err == nil {
					ipv6Addr = iapd.PD.Prefix
					leaseTime = iapd.PD.ValidLifeTime
					logger.Debugw(ctx, "IPv6 Allocated", log.Fields{"IAPD IPv6": ipv6Addr})
					break
				} else {
					logger.Warnw(ctx, "Decode of IAPD Failed", log.Fields{"Reason": err.Error()})
					break
				}
			}
		}
	}
	return ipv6Addr, leaseTime
}

// ProcessDsDhcpv4Packet : DHCPv4 packet processor functions
// This function processes DS DHCP packet received on the NNI port.
// The services are attached to the access ports. Thus, the DHCP
// session is derived from the list of DHCP sessions stored in the
// common map. The key for retrieval includes the VLAN tags in the
// the packet and the MAC address of the client.
func (va *VoltApplication) ProcessDsDhcpv4Packet(cntx context.Context, device string, port string, pkt gopacket.Packet) {
	// Retrieve the layers to build the outgoing packet. It is not
	// possible to add/remove layers to the existing packet and thus
	// the lyayers are extracted to build the outgoing packet
	eth := pkt.Layer(layers.LayerTypeEthernet).(*layers.Ethernet)
	ip := pkt.Layer(layers.LayerTypeIPv4).(*layers.IPv4)
	udp := pkt.Layer(layers.LayerTypeUDP).(*layers.UDP)
	dhcp4 := pkt.Layer(layers.LayerTypeDHCPv4).(*layers.DHCPv4)
	msgType := DhcpMsgType(dhcp4)

	// Need to locate the service from the packet alone as the services
	// are not attached to NNI port. The service is stored on DHCP relay
	// application
	logger.Infow(ctx, "Processing Southbound DS DHCPv4 packet", log.Fields{"Port": port, "Type": msgType})

	// Retrieve the priority and drop eligible flags from the
	// packet received
	var priority uint8
	var dsPbit uint8
	var dropEligible bool
	dot1ql := pkt.Layer(layers.LayerTypeDot1Q)
	if dot1ql != nil {
		dot1q := dot1ql.(*layers.Dot1Q)
		priority = dot1q.Priority
		dropEligible = dot1q.DropEligible
	}

	pktInnerlan, pktOuterlan := GetVlansFromPacket(pkt)
	vpvList, _ := GetVnetForV4Nni(dhcp4, pktInnerlan, pktOuterlan, priority)
	if len(vpvList) == 0 {
		logger.Warn(ctx, "VNET couldn't be found for NNI")
		return
	}

	// The DHCP option 82, if it exists is removed from the packet
	DelOption82(dhcp4)
	ipAddr, leaseTime := GetIpv4Addr(dhcp4)

	for _, vpv := range vpvList {
		dsPbit = vpv.GetRemarkedPriority(priority)
		// Raise DHCP ACK/NCK indication
		if vpv.DhcpRelay {
			// Inform dhcp response information to dhcp server handler
			dhcpResponseReceived(uint16(vpv.CVlan), uint16(vpv.SVlan))
			// Process the Ack/Nack to track to state of the IP layer of the connection
			if msgType == layers.DHCPMsgTypeAck || msgType == layers.DHCPMsgTypeNak {
				// Install DS HSIA flows after DHCP ACK.
				if msgType == layers.DHCPMsgTypeAck {
					// Voltha will push US and DS HSIA flow on receivng the DS HSIA
					// flow installation request, VGC to update US HSIA flow with leanrt MAC.
					// separate go rotuine is spawned to avoid drop of ACK packet
					// as HSIA flows will be deleted if new MAC is learnt.
					go vpv.SetMacAddr(cntx, dhcp4.ClientHWAddr)
				}
				vpv.DhcpResultInd(cntx, dhcp4)
			}
			raiseDHCPv4Indication(msgType, vpv, dhcp4.ClientHWAddr, ipAddr, dsPbit, device, leaseTime)
		}

		// Create the outgoing bufer and set the checksum in the packet
		buff := gopacket.NewSerializeBuffer()
		if err := udp.SetNetworkLayerForChecksum(ip); err != nil {
			logger.Error(ctx, "Error in setting checksum")
			return
		}
		opts := gopacket.SerializeOptions{
			FixLengths:       true,
			ComputeChecksums: true,
		}

		cTagType := layers.EthernetTypeIPv4
		eth.EthernetType = layers.EthernetTypeDot1Q

		var pktLayers []gopacket.SerializableLayer
		pktLayers = append(pktLayers, eth)

		var qVlans []of.VlanType
		var qVlanLayers []gopacket.SerializableLayer

		if vpv.AllowTransparent {
			vlanThreshold := 2
			// In case of ONU_CVLAN or OLT_SVLAN, the DS pkts have single configured vlan
			// In case of ONU_CVLAN_OLT_SVLAN or OLT_CVLAN_OLT_SVLAN, the DS pkts have 2 configured vlan
			// Based on that, the no. of vlans should be ignored to get only transparent vlans
			if vpv.VlanControl == ONUCVlan || vpv.VlanControl == OLTSVlan || vpv.VlanControl == None {
				vlanThreshold = 1
			}
			nxtLayer := layers.EthernetTypeDot1Q
			if vlans := GetVlans(pkt); len(vlans) > vlanThreshold {
				qVlans = vlans[vlanThreshold:]
				cTagType = layers.EthernetTypeDot1Q
			}
			for i, qVlan := range qVlans {
				vlan := uint16(qVlan)
				if i == (len(qVlans) - 1) {
					nxtLayer = layers.EthernetTypeIPv4
				}
				qdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: vlan, DropEligible: dropEligible, Type: nxtLayer}
				qVlanLayers = append(qVlanLayers, qdot1q)
			}
		}
		switch vpv.VlanControl {
		case ONUCVlanOLTSVlan:
			cdot1q := &layers.Dot1Q{Priority: dsPbit, VLANIdentifier: uint16(vpv.CVlan), DropEligible: dropEligible, Type: cTagType}
			pktLayers = append(pktLayers, cdot1q)
		case ONUCVlan,
			None:
			sdot1q := &layers.Dot1Q{Priority: dsPbit, VLANIdentifier: uint16(vpv.SVlan), DropEligible: dropEligible, Type: cTagType}
			pktLayers = append(pktLayers, sdot1q)
		case OLTCVlanOLTSVlan,
			OLTSVlan:
			udot1q := &layers.Dot1Q{Priority: dsPbit, VLANIdentifier: uint16(vpv.UniVlan), DropEligible: dropEligible, Type: cTagType}
			pktLayers = append(pktLayers, udot1q)
		default:
			logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
		}

		pktLayers = append(pktLayers, qVlanLayers...)
		pktLayers = append(pktLayers, ip)
		pktLayers = append(pktLayers, udp)
		pktLayers = append(pktLayers, dhcp4)
		logger.Debugw(ctx, "Layers Count", log.Fields{"Count": len(pktLayers)})
		if err := gopacket.SerializeMultiLayers(buff, opts, pktLayers); err != nil {
			logger.Errorw(ctx, "Packet Serialization Failed", log.Fields{"Reason": err.Error()})
			return
		}

		if err := cntlr.GetController().PacketOutReq(device, vpv.Port, port, buff.Bytes(), false); err != nil {
			logger.Errorw(ctx, "PacketOutReq Failed", log.Fields{"Error": err})
		}
	}
}

// raiseDHCPv4Indication process DHCPv4 packet and raise indication
func raiseDHCPv4Indication(msgType layers.DHCPMsgType, vpv *VoltPortVnet, smac net.HardwareAddr,
	ip net.IP, pktPbit uint8, device string, leaseTime int64) {
	logger.Debugw(ctx, "Processing Dhcpv4 packet", log.Fields{"ethsrcMac": smac.String(),
		"MacLearningInVPV": vpv.MacLearning, "MacConfigured": vpv.MacAddr, "dhcpType": msgType,
		"vlanPriority": pktPbit, "VPVLearntMac": vpv.LearntMacAddr})

	matchServiceAndRaiseInd := func(key, value interface{}) bool {
		// walk through all svcs under vpv and match pbit with packet.
		svc := value.(*VoltService)

		if svc.IsPbitExist(of.PbitType(pktPbit)) {
			logger.Debugw(ctx, "Matching Pbit found in service config", log.Fields{"ServiceName": svc.Name, "Pbit": pktPbit})
			return false
		}
		return true
	}

	switch msgType {
	case layers.DHCPMsgTypeDiscover, layers.DHCPMsgTypeRequest:
		if msgType == layers.DHCPMsgTypeDiscover {
			vpv.SetDhcpState(DhcpRelayStateDiscover)
		} else if msgType == layers.DHCPMsgTypeRequest {
			vpv.SetDhcpState(DhcpRelayStateRequest)
		}
	// Reset learnt mac address in case of DHCPv4 release
	case layers.DHCPMsgTypeRelease:
		vpv.LearntMacAddr, _ = net.ParseMAC("00:00:00:00:00:00")
		vpv.services.Range(matchServiceAndRaiseInd)
		vpv.SetDhcpState(DhcpRelayStateRelease)

	case layers.DHCPMsgTypeAck, layers.DHCPMsgTypeNak:
		vpv.services.Range(matchServiceAndRaiseInd)
		if msgType == layers.DHCPMsgTypeAck {
			vpv.SetDhcpState(DhcpRelayStateAck)
		} else if msgType == layers.DHCPMsgTypeNak {
			vpv.SetDhcpState(DhcpRelayStateNAK)
		}
	case layers.DHCPMsgTypeOffer:
		vpv.SetDhcpState(DhcpRelayStateOffer)
	}
}

// raiseDHCPv6Indication process DHCPv6 packet and raise indication
func raiseDHCPv6Indication(msgType layers.DHCPv6MsgType, vpv *VoltPortVnet,
	smac net.HardwareAddr, ip net.IP, pktPbit uint8, device string, leaseTime uint32) {
	logger.Debugw(ctx, "Processing DHCPv6 packet", log.Fields{"dhcpType": msgType,
		"vlanPriority": pktPbit, "dhcpClientMac": smac.String(),
		"MacLearningInVPV": vpv.MacLearning, "MacConfigured": vpv.MacAddr,
		"VPVLearntMac": vpv.LearntMacAddr})

	matchServiceAndRaiseInd := func(key, value interface{}) bool {
		svc := value.(*VoltService)
		if svc.IsPbitExist(of.PbitType(pktPbit)) {
			logger.Debugw(ctx, "Matching Pbit found in service config", log.Fields{"ServiceName": svc.Name, "Pbit": pktPbit})
			return false
		}
		return true
	}

	switch msgType {
	case layers.DHCPv6MsgTypeSolicit:
		vpv.SetDhcpv6State(Dhcpv6RelayStateSolicit)
	// Reset learnt mac address in case of DHCPv6 release
	case layers.DHCPv6MsgTypeRelease:
		vpv.LearntMacAddr, _ = net.ParseMAC("00:00:00:00:00:00")
		vpv.services.Range(matchServiceAndRaiseInd)
		vpv.SetDhcpv6State(Dhcpv6RelayStateRelease)

	case layers.DHCPv6MsgTypeReply:
		vpv.services.Range(matchServiceAndRaiseInd)
		vpv.SetDhcpv6State(Dhcpv6RelayStateReply)
	}
}

// ProcessUsDhcpv4Packet : The US DHCPv4 packet is identified the DHCP OP in the packet. A request is considered upstream
// and the service associated with the packet is located by the port and VLANs in the packet
func (va *VoltApplication) ProcessUsDhcpv4Packet(cntx context.Context, device string, port string, pkt gopacket.Packet) {
	// We received the packet on an access port and the service for the packet can be
	// gotten from the port and the packet
	vpv, svc := va.GetVnetFromPkt(device, port, pkt)
	if vpv == nil {
		logger.Warn(ctx, "VNET couldn't be found from packet")
		return
	}

	outport, _ := va.GetNniPort(device)
	if outport == "" || outport == "0" {
		logger.Errorw(ctx, "NNI Port not found for device. Dropping Packet", log.Fields{"NNI": outport})
		return
	}

	// Extract the layers in the packet to prepare the outgoing packet
	// We use the layers to build the outgoing packet from scratch as
	// the packet received can't be modified to add/remove layers
	eth := pkt.Layer(layers.LayerTypeEthernet).(*layers.Ethernet)
	ip := pkt.Layer(layers.LayerTypeIPv4).(*layers.IPv4)
	udp := pkt.Layer(layers.LayerTypeUDP).(*layers.UDP)
	dhcp4 := pkt.Layer(layers.LayerTypeDHCPv4).(*layers.DHCPv4)
	msgType := DhcpMsgType(dhcp4)
	logger.Infow(ctx, "Processing Southbound US DHCPv4 packet", log.Fields{"Device": device, "Port": port, "Type": msgType})

	// Learn the 8021P values from the packet received
	var priority uint8
	var dropEligible bool
	dot1ql := pkt.Layer(layers.LayerTypeDot1Q)
	if dot1ql != nil {
		dot1q := dot1ql.(*layers.Dot1Q)
		priority = dot1q.Priority
		dropEligible = dot1q.DropEligible
	}
	// If this is the first message in the DHCP sequence, the service
	// is added to the DHCP relay application. The reply packets locate
	// the associated service/session from the relay application.
	if msgType == layers.DHCPMsgTypeDiscover || msgType == layers.DHCPMsgTypeRequest {
		if err := dhcpNws.AddDhcpSession(pkt, vpv); err != nil {
			logger.Errorw(ctx, "Adding dhcp session failed", log.Fields{"Error": err})
		}
	}

	// Raise mac-learnt(DHCP Discover) indication when mac learning is enabled and learnt mac
	// is not same as received mac address. If mac learning disabled, we have mac address in the
	// service configuration. Hence mac learnt indication is not raised
	// Reset learnt mac address in case of DHCP release and raise the indication
	if vpv.DhcpRelay {
		// If this is the first message in the DHCP sequence, the service
		// is added to the DHCP relay application. The reply packets locate
		// the associated service/session from the relay application.
		// DS HSIA flows will be added after DHCP ACK .
		if msgType == layers.DHCPMsgTypeDiscover || msgType == layers.DHCPMsgTypeRequest {
			if !util.MacAddrsMatch(vpv.MacAddr, dhcp4.ClientHWAddr) {
				// MAC is different and relearning is disabled.
				if NonZeroMacAddress(vpv.MacAddr) && vpv.MacLearning == Learn {
					// update learnt mac for debug purpose
					vpv.LearntMacAddr = dhcp4.ClientHWAddr
					vpv.WriteToDb(cntx)
					logger.Warnw(ctx, "Dropping the packet Mac relearn is disabled",
						log.Fields{"vpv.MacAddr": vpv.MacAddr, "LearntMac": dhcp4.ClientHWAddr})
					return
				}
				expectedPort := va.GetMacInPortMap(dhcp4.ClientHWAddr)
				if expectedPort != "" && expectedPort != vpv.Port {
					logger.Errorw(ctx, "mac-learnt-from-different-port-ignoring-dhcp-message", log.Fields{"MsgType": msgType, "ExpectedPort": expectedPort, "ReceivedPort": vpv.Port, "LearntMacAdrr": vpv.MacAddr, "NewMacAdrr": dhcp4.ClientHWAddr.String()})
					return
				}
			}
		}
		raiseDHCPv4Indication(msgType, vpv, dhcp4.ClientHWAddr, vpv.Ipv4Addr, priority, device, 0)

		// Check IsOption82Enabled flag in configuration. if true(enabled), add option82 into dhcpv4 header.
		// Remote id can be custom or mac address.
		// If remote id is custom, then add service will carry the remote id
		// If remote id is mac address, and if mac is configured, then add service will carry the remote id
		// If remote id is mac address, in mac learning case, then mac has to be taken from dhcp packet
		if svc.IsOption82Enabled {
			var remoteID []byte
			if svc.RemoteIDType == string(MACAddress) {
				remoteID = []byte((dhcp4.ClientHWAddr).String())
			} else if svc.RemoteID != nil {
				remoteID = svc.RemoteID
			}
			AddDhcpv4Option82(svc, remoteID, dhcp4)
		}
	}

	buff := gopacket.NewSerializeBuffer()
	if err := udp.SetNetworkLayerForChecksum(ip); err != nil {
		logger.Error(ctx, "Error in setting checksum")
		return
	}
	opts := gopacket.SerializeOptions{
		FixLengths:       true,
		ComputeChecksums: true,
	}

	cTagType := layers.EthernetTypeIPv4
	outerVlan, innerVlan := vpv.GetNniVlans()
	logger.Debugw(ctx, "Vnet Vlans", log.Fields{"Svlan": outerVlan, "Cvlan": innerVlan})
	eth.EthernetType = vpv.SVlanTpid

	var pktLayers []gopacket.SerializableLayer
	pktLayers = append(pktLayers, eth)

	var qVlans []of.VlanType
	var qVlanLayers []gopacket.SerializableLayer

	if vpv.AllowTransparent {
		nxtLayer := layers.EthernetTypeDot1Q
		if vlans := GetVlans(pkt); len(vlans) > 1 {
			qVlans = vlans[1:]
			logger.Debugw(ctx, "Q Vlans", log.Fields{"Vlan List": qVlans})
			cTagType = layers.EthernetTypeDot1Q
		}
		for i, qVlan := range qVlans {
			vlan := uint16(qVlan)
			if i == (len(qVlans) - 1) {
				nxtLayer = layers.EthernetTypeIPv4
			}
			qdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: vlan, DropEligible: dropEligible, Type: nxtLayer}
			qVlanLayers = append(qVlanLayers, qdot1q)
		}
	}
	switch vpv.VlanControl {
	case ONUCVlanOLTSVlan,
		OLTCVlanOLTSVlan:
		sdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: outerVlan, DropEligible: dropEligible, Type: layers.EthernetTypeDot1Q}
		pktLayers = append(pktLayers, sdot1q)
		cdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: innerVlan, DropEligible: dropEligible, Type: cTagType}
		pktLayers = append(pktLayers, cdot1q)
	case ONUCVlan,
		OLTSVlan,
		None:
		cdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: outerVlan, DropEligible: dropEligible, Type: cTagType}
		pktLayers = append(pktLayers, cdot1q)
	default:
		logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
	}

	pktLayers = append(pktLayers, qVlanLayers...)
	pktLayers = append(pktLayers, ip)
	pktLayers = append(pktLayers, udp)
	pktLayers = append(pktLayers, dhcp4)
	logger.Debugw(ctx, "Layers Count", log.Fields{"Count": len(pktLayers)})
	if err := gopacket.SerializeMultiLayers(buff, opts, pktLayers); err != nil {
		return
	}

	// Now the packet constructed is output towards the switch to be emitted on
	// the NNI port
	if err := cntlr.GetController().PacketOutReq(device, outport, port, buff.Bytes(), false); err != nil {
		logger.Errorw(ctx, "PacketOutReq Failed", log.Fields{"Error": err})
	}
	if vpv.DhcpRelay {
		// Inform dhcp request information to dhcp server handler
		dhcpRequestReceived(uint16(vpv.CVlan), uint16(vpv.SVlan), eth.SrcMAC.String())
	}
}

// ProcessUDP4Packet : CallBack function registered with application to handle DHCP packetIn
func ProcessUDP4Packet(cntx context.Context, device string, port string, pkt gopacket.Packet) {
	GetApplication().ProcessUDP4Packet(cntx, device, port, pkt)
}

// ProcessUDP4Packet : The packet is a UDP packet and currently only DHCP relay application is supported
// We determine the packet direction and process it based on the direction
func (va *VoltApplication) ProcessUDP4Packet(cntx context.Context, device string, port string, pkt gopacket.Packet) {
	// Currently DHCP is the only application supported by the application
	// We check for DHCP before proceeding further. In future, this could be
	// based on registration and the callbacks
	dhcpl := pkt.Layer(layers.LayerTypeDHCPv4)
	if dhcpl == nil {
		return
	}
	//logger.Debugw(ctx, "Received Packet In", log.Fields{"Pkt": hex.EncodeToString(pkt.Data())})
	dhcp4 := pkt.Layer(layers.LayerTypeDHCPv4).(*layers.DHCPv4)
	if dhcp4.Operation == layers.DHCPOpRequest {
		// This is treated as an upstream packet in the VOLT application
		// as VOLT serves access subscribers who use DHCP to acquire IP
		// address and these packets go upstream to the network
		va.ProcessUsDhcpv4Packet(cntx, device, port, pkt)
	} else {
		// This is a downstream packet
		va.ProcessDsDhcpv4Packet(cntx, device, port, pkt)
	}
}

// ProcessUDP6Packet : CallBack function registered with application to handle DHCPv6 packetIn
func ProcessUDP6Packet(cntx context.Context, device string, port string, pkt gopacket.Packet) {
	GetApplication().ProcessUDP6Packet(cntx, device, port, pkt)
}

// ProcessUDP6Packet : As a LDRA node, we expect to see only RelayReply from the DHCP server and we always
// pack the received request and send it to the server as a RelayForward message
// We expect to see Solicit, Request in the most normal cases. Before the lease expires
// we should also see Renew. However, we should always pack the US message by adding
// additional option that identifies to the server that the DHCP packet is forwarded
// by an LDRA node.
func (va *VoltApplication) ProcessUDP6Packet(cntx context.Context, device string, port string, pkt gopacket.Packet) []byte {
	dhcpl := pkt.Layer(layers.LayerTypeDHCPv6)
	if dhcpl == nil {
		return nil
	}
	logger.Infow(ctx, "Processing DHCPv6 packet", log.Fields{"Port": port})
	dhcpv6 := dhcpl.(*layers.DHCPv6)
	switch dhcpv6.MsgType {
	case layers.DHCPv6MsgTypeSolicit, layers.DHCPv6MsgTypeRequest, layers.DHCPv6MsgTypeRenew,
		layers.DHCPv6MsgTypeRelease, layers.DHCPv6MsgTypeRebind, layers.DHCPv6MsgTypeInformationRequest,
		layers.DHCPv6MsgTypeDecline:
		va.ProcessUsDhcpv6Packet(cntx, device, port, pkt)
	case layers.DHCPv6MsgTypeAdvertise, layers.DHCPv6MsgTypeConfirm, layers.DHCPv6MsgTypeReconfigure:
		logger.Warnw(ctx, "SouthBound DHCPv6 DS Messages Expected For a Relay Agent", log.Fields{"Type": dhcpv6.MsgType})
	case layers.DHCPv6MsgTypeRelayForward:
		logger.Warn(ctx, "As the first DHCPv6 Relay Agent, Unexpected Relay Forward")
	case layers.DHCPv6MsgTypeRelayReply:
		// We received a response from the server
		va.ProcessDsDhcpv6Packet(cntx, device, port, pkt)
	}
	return nil
}

// GetRelayReplyBytes to get relay reply bytes
func GetRelayReplyBytes(dhcp6 *layers.DHCPv6) []byte {
	for _, o := range dhcp6.Options {
		logger.Infow(ctx, "Received Option", log.Fields{"Code": o.Code})
		if o.Code == layers.DHCPv6OptRelayMessage {
			return o.Data
		}
	}
	return nil
}

// BuildRelayFwd to build forward relay
func BuildRelayFwd(paddr net.IP, intfID []byte, remoteID []byte, payload []byte, isOption82Enabled bool, dhcpRelay bool) *layers.DHCPv6 {
	dhcp6 := &layers.DHCPv6{MsgType: layers.DHCPv6MsgTypeRelayForward, LinkAddr: net.ParseIP("::"), PeerAddr: []byte(paddr)}
	dhcp6.Options = append(dhcp6.Options, layers.NewDHCPv6Option(layers.DHCPv6OptRelayMessage, payload))
	// Check IsOption82Enabled flag in configuration. if true(enabled), add remoteID and circuitID into dhcpv6 header.
	if dhcpRelay {
		if isOption82Enabled {
			remote := &layers.DHCPv6RemoteId{RemoteId: remoteID}
			if len(remoteID) != 0 {
				dhcp6.Options = append(dhcp6.Options, layers.NewDHCPv6Option(layers.DHCPv6OptRemoteID, remote.Encode()))
			}
			if len(intfID) != 0 {
				intf := &layers.DHCPv6IntfId{Data: intfID}
				dhcp6.Options = append(dhcp6.Options, layers.NewDHCPv6Option(layers.DHCPv6OptInterfaceID, intf.Encode()))
			}
		}
	}
	return dhcp6
}

// nolint: gocyclo
// ProcessUsDhcpv6Packet to rpocess upstream DHCPv6 packet
func (va *VoltApplication) ProcessUsDhcpv6Packet(cntx context.Context, device string, port string, pkt gopacket.Packet) {
	// We received the packet on an access port and the service for the packet can be
	// gotten from the port and the packet
	logger.Infow(ctx, "Processing Southbound US DHCPv6 packet", log.Fields{"Port": port})
	logger.Debugw(ctx, "Packet IN", log.Fields{"Pkt": hex.EncodeToString(pkt.Data())})
	vpv, svc := va.GetVnetFromPkt(device, port, pkt)
	if vpv == nil {
		logger.Warn(ctx, "VNET couldn't be found from packet")
		return
	}

	outport, _ := va.GetNniPort(device)
	if outport == "" || outport == "0" {
		logger.Errorw(ctx, "NNI Port not found for device. Dropping Packet", log.Fields{"NNI": outport})
		return
	}

	// Extract the layers in the packet to prepare the outgoing packet
	// We use the layers to build the outgoing packet from scratch as
	// the packet received can't be modified to add/remove layers
	eth := pkt.Layer(layers.LayerTypeEthernet).(*layers.Ethernet)
	ip := pkt.Layer(layers.LayerTypeIPv6).(*layers.IPv6)
	udp := pkt.Layer(layers.LayerTypeUDP).(*layers.UDP)
	idhcp6 := pkt.Layer(layers.LayerTypeDHCPv6).(*layers.DHCPv6)

	// Remote id can be custom or mac address.
	// If remote id is custom, then add service will carry the remote id
	// If remote id is mac address, and if mac is configured, then add service will carry the remote id
	// If remote id is mac address, in mac learning case, then mac has to be taken from dhcp packet
	var remoteID []byte
	if svc.RemoteIDType == string(MACAddress) {
		remoteID = []byte((eth.SrcMAC).String())
	} else if svc.RemoteID != nil {
		remoteID = svc.RemoteID
	}
	dhcp6 := BuildRelayFwd(ip.SrcIP, svc.GetCircuitID(), remoteID, udp.Payload, svc.IsOption82Enabled, vpv.DhcpRelay)

	var sourceMac = eth.SrcMAC
	var sessionKey [MaxLenDhcpv6DUID]byte

	clientDuid, decodedDuid := getDhcpv6ClientDUID(idhcp6)
	if clientDuid == nil || decodedDuid == nil {
		copy(sessionKey[:], eth.SrcMAC)
	} else {
		copy(sessionKey[:], clientDuid[0:])
		if decodedDuid.Type == layers.DHCPv6DUIDTypeLLT || decodedDuid.Type == layers.DHCPv6DUIDTypeLL {
			sourceMac = decodedDuid.LinkLayerAddress
		}
	}
	// Learn the 8021P values from the packet received
	var priority uint8
	var dropEligible bool
	dot1ql := pkt.Layer(layers.LayerTypeDot1Q)
	if dot1ql != nil {
		dot1q := dot1ql.(*layers.Dot1Q)
		priority = dot1q.Priority
		dropEligible = dot1q.DropEligible
	}
	if idhcp6.MsgType == layers.DHCPv6MsgTypeSolicit {
		if err := dhcpNws.AddDhcp6Session(sessionKey, vpv); err != nil {
			logger.Errorw(ctx, "Adding dhcpv6 session failed", log.Fields{"Error": err})
		}
		vpv.DHCPv6DUID = sessionKey
	}

	// Raise mac-learnt(DHCPv6MsgTypeSolicit) indication when mac learning is enabled and learnt mac
	// is not same as received mac address. If mac learning disabled, we have mac address in the
	// service configuration. Hence mac learnt indication is not raised
	if vpv.DhcpRelay {
		if idhcp6.MsgType == layers.DHCPv6MsgTypeSolicit {
			if !util.MacAddrsMatch(vpv.MacAddr, sourceMac) {
				// MAC is different and relearning is disabled.
				if NonZeroMacAddress(vpv.MacAddr) && vpv.MacLearning == Learn {
					// update learnt mac for debug purpose
					vpv.LearntMacAddr = sourceMac
					vpv.WriteToDb(cntx)
					logger.Warnw(ctx, "Dropping the packet Mac relearn is disabled",
						log.Fields{"vpv.MacAddr": vpv.MacAddr, "LearntMac": sourceMac})
					return
				}
				expectedPort := va.GetMacInPortMap(sourceMac)
				if expectedPort != "" && expectedPort != vpv.Port {
					logger.Errorw(ctx, "mac-learnt-from-different-port-ignoring-dhcp-message", log.Fields{"MsgType": idhcp6.MsgType, "ExpectedPort": expectedPort, "ReceivedPort": vpv.Port, "LearntMacAdrr": vpv.MacAddr, "NewMacAdrr": sourceMac.String()})
					return
				}
			}
		}
		raiseDHCPv6Indication(idhcp6.MsgType, vpv, sourceMac, vpv.Ipv6Addr, priority, device, 0)
	}

	// Create the buffer and the encode options for the outgoing packet
	buff := gopacket.NewSerializeBuffer()
	if err := udp.SetNetworkLayerForChecksum(ip); err != nil {
		logger.Error(ctx, "Error in setting checksum")
		return
	}
	opts := gopacket.SerializeOptions{
		FixLengths:       true,
		ComputeChecksums: true,
	}

	cTagType := layers.EthernetTypeIPv6
	outerVlan, innerVlan := vpv.GetNniVlans()
	eth.EthernetType = vpv.SVlanTpid

	var pktLayers []gopacket.SerializableLayer
	pktLayers = append(pktLayers, eth)

	var qVlans []of.VlanType
	var qVlanLayers []gopacket.SerializableLayer

	if vpv.AllowTransparent {
		nxtLayer := layers.EthernetTypeDot1Q
		if vlans := GetVlans(pkt); len(vlans) > 1 {
			qVlans = vlans[1:]
			cTagType = layers.EthernetTypeDot1Q
		}
		for i, qVlan := range qVlans {
			vlan := uint16(qVlan)
			if i == (len(qVlans) - 1) {
				nxtLayer = layers.EthernetTypeIPv6
			}
			qdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: vlan, DropEligible: dropEligible, Type: nxtLayer}
			qVlanLayers = append(qVlanLayers, qdot1q)
		}
	}
	switch vpv.VlanControl {
	case ONUCVlanOLTSVlan,
		OLTCVlanOLTSVlan:
		sdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: outerVlan, DropEligible: dropEligible, Type: layers.EthernetTypeDot1Q}
		pktLayers = append(pktLayers, sdot1q)
		cdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: innerVlan, DropEligible: dropEligible, Type: cTagType}
		pktLayers = append(pktLayers, cdot1q)
	case ONUCVlan,
		OLTSVlan,
		None:
		cdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: outerVlan, DropEligible: dropEligible, Type: cTagType}
		pktLayers = append(pktLayers, cdot1q)
	default:
		logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
	}

	pktLayers = append(pktLayers, qVlanLayers...)
	pktLayers = append(pktLayers, ip)
	pktLayers = append(pktLayers, udp)
	pktLayers = append(pktLayers, dhcp6)
	logger.Debugw(ctx, "Layers Count", log.Fields{"Count": len(pktLayers)})
	if err := gopacket.SerializeMultiLayers(buff, opts, pktLayers); err != nil {
		return
	}
	// Now the packet constructed is output towards the switch to be emitted on
	// the NNI port
	if err := cntlr.GetController().PacketOutReq(device, outport, port, buff.Bytes(), false); err != nil {
		logger.Errorw(ctx, "PacketOutReq Failed", log.Fields{"Error": err})
	}
	if vpv.DhcpRelay {
		// Inform dhcp request information to dhcp server handler
		dhcpRequestReceived(uint16(vpv.CVlan), uint16(vpv.SVlan), eth.SrcMAC.String())
	}
}

// GetDhcpv6 to get dhcpv6 info
func GetDhcpv6(payload []byte) (*layers.DHCPv6, error) {
	pkt := gopacket.NewPacket(payload, layers.LayerTypeDHCPv6, gopacket.Default)
	if dl := pkt.Layer(layers.LayerTypeDHCPv6); dl != nil {
		if dhcp6, ok := dl.(*layers.DHCPv6); ok {
			return dhcp6, nil
		}
	}
	return nil, errors.New("Failed to decode DHCPv6")
}

// ProcessDsDhcpv6Packet to process downstream dhcpv6 packet
func (va *VoltApplication) ProcessDsDhcpv6Packet(cntx context.Context, device string, port string, pkt gopacket.Packet) {
	logger.Infow(ctx, "Processing Southbound DS DHCPv6 packet", log.Fields{"Port": port})
	logger.Debugw(ctx, "Packet IN", log.Fields{"Pkt": hex.EncodeToString(pkt.Data())})

	// Retrieve the layers to build the outgoing packet. It is not
	// possible to add/remove layers to the existing packet and thus
	// the lyayers are extracted to build the outgoing packet
	// The DHCP layer is handled differently. The Relay-Reply option
	// of DHCP is extracted and is made the UDP payload.
	eth := pkt.Layer(layers.LayerTypeEthernet).(*layers.Ethernet)
	ip := pkt.Layer(layers.LayerTypeIPv6).(*layers.IPv6)
	udp := pkt.Layer(layers.LayerTypeUDP).(*layers.UDP)
	idhcp6 := pkt.Layer(layers.LayerTypeDHCPv6).(*layers.DHCPv6)
	//var dhcp6 *layers.DHCPv6
	var payload []byte
	if payload = GetRelayReplyBytes(idhcp6); payload == nil {
		logger.Warn(ctx, "Didn't Receive RelayMessage IE")
		return
	}

	dhcp6, err := GetDhcpv6(payload)
	if err != nil {
		logger.Warnw(ctx, "DHCPv6 Decode Failed", log.Fields{"Reason": err.Error()})
		return
	}

	// Learn the 8021P values from the packet received
	var priority uint8
	var dsPbit uint8
	var dropEligible bool
	dot1ql := pkt.Layer(layers.LayerTypeDot1Q)
	if dot1ql != nil {
		dot1q := dot1ql.(*layers.Dot1Q)
		priority = dot1q.Priority
		dropEligible = dot1q.DropEligible
	}

	pktInnerlan, pktOuterlan := GetVlansFromPacket(pkt)
	vpvList, clientMac, err := GetVnetForV6Nni(dhcp6, pktInnerlan, pktOuterlan, priority, eth.DstMAC)
	if len(vpvList) == 0 {
		logger.Warnw(ctx, "VNET couldn't be found for NNI", log.Fields{"Reason": err})
		return
	}

	ipv6Addr, leaseTime := GetIpv6Addr(dhcp6)

	for _, vpv := range vpvList {
		dsPbit = vpv.GetRemarkedPriority(priority)
		// Raise DHCPv6 Reply indication
		if vpv.DhcpRelay {
			// Inform dhcp response information to dhcp server handler
			dhcpResponseReceived(uint16(vpv.CVlan), uint16(vpv.SVlan))

			if dhcp6.MsgType == layers.DHCPv6MsgTypeReply && ipv6Addr != nil {
				// separate go rotuine is spawned to avoid drop of ACK packet
				// as HSIA flows will be deleted if new MAC is learnt.
				if len(vpvList) == 1 {
					go vpv.SetMacAddr(cntx, clientMac)
				}
				vpv.Dhcpv6ResultInd(cntx, ipv6Addr, leaseTime)
			}
			raiseDHCPv6Indication(dhcp6.MsgType, vpv, clientMac, ipv6Addr, dsPbit, device, leaseTime)
		}

		//Replace dst Port value to 546
		udp.DstPort = 546
		logger.Infow(ctx, "Packet Out UDP Port..", log.Fields{"UDP": udp, "Port": udp.DstPort})

		// Create the buffer and the encode options for the outgoing packet
		buff := gopacket.NewSerializeBuffer()
		if err := udp.SetNetworkLayerForChecksum(ip); err != nil {
			logger.Error(ctx, "Error in setting checksum")
			return
		}
		opts := gopacket.SerializeOptions{
			FixLengths:       true,
			ComputeChecksums: true,
		}

		cTagType := layers.EthernetTypeIPv6
		eth.EthernetType = layers.EthernetTypeDot1Q

		var pktLayers []gopacket.SerializableLayer
		pktLayers = append(pktLayers, eth)

		var qVlans []of.VlanType
		var qVlanLayers []gopacket.SerializableLayer

		if vpv.AllowTransparent {
			vlanThreshold := 2
			// In case of ONU_CVLAN or OLT_SVLAN, the DS pkts have single configured vlan
			// In case of ONU_CVLAN_OLT_SVLAN or OLT_CVLAN_OLT_SVLAN, the DS pkts have 2 configured vlan
			// Based on that, the no. of vlans should be ignored to get only transparent vlans
			if vpv.VlanControl == ONUCVlan || vpv.VlanControl == OLTSVlan || vpv.VlanControl == None {
				vlanThreshold = 1
			}
			nxtLayer := layers.EthernetTypeDot1Q
			if vlans := GetVlans(pkt); len(vlans) > vlanThreshold {
				qVlans = vlans[vlanThreshold:]
				cTagType = layers.EthernetTypeDot1Q
			}
			for i, qVlan := range qVlans {
				vlan := uint16(qVlan)
				if i == (len(qVlans) - 1) {
					nxtLayer = layers.EthernetTypeIPv6
				}
				qdot1q := &layers.Dot1Q{Priority: priority, VLANIdentifier: vlan, DropEligible: dropEligible, Type: nxtLayer}
				qVlanLayers = append(qVlanLayers, qdot1q)
			}
		}
		switch vpv.VlanControl {
		case ONUCVlanOLTSVlan:
			cdot1q := &layers.Dot1Q{Priority: dsPbit, VLANIdentifier: uint16(vpv.CVlan), DropEligible: dropEligible, Type: cTagType}
			pktLayers = append(pktLayers, cdot1q)
		case ONUCVlan,
			None:
			sdot1q := &layers.Dot1Q{Priority: dsPbit, VLANIdentifier: uint16(vpv.SVlan), DropEligible: dropEligible, Type: cTagType}
			pktLayers = append(pktLayers, sdot1q)
		case OLTCVlanOLTSVlan,
			OLTSVlan:
			udot1q := &layers.Dot1Q{Priority: dsPbit, VLANIdentifier: uint16(vpv.UniVlan), DropEligible: dropEligible, Type: cTagType}
			pktLayers = append(pktLayers, udot1q)
		default:
			logger.Errorw(ctx, "Invalid Vlan Control Option", log.Fields{"Value": vpv.VlanControl})
		}

		pktLayers = append(pktLayers, qVlanLayers...)
		pktLayers = append(pktLayers, ip)
		pktLayers = append(pktLayers, udp)
		pktLayers = append(pktLayers, dhcp6)
		logger.Debugw(ctx, "Layers Count", log.Fields{"Count": len(pktLayers)})
		if err := gopacket.SerializeMultiLayers(buff, opts, pktLayers); err != nil {
			logger.Errorw(ctx, "Packet Serialization Failed", log.Fields{"Reason": err.Error()})
			return
		}

		if err := cntlr.GetController().PacketOutReq(device, vpv.Port, port, buff.Bytes(), false); err != nil {
			logger.Errorw(ctx, "PacketOutReq Failed", log.Fields{"Reason": err.Error()})
		}
	}
}

// The DHCP relay application is maintained within the structures below
var dhcpNws *DhcpNetworks

func init() {
	dhcpNws = NewDhcpNetworks()
}

type DhcpAllocation struct {
	SubscriberID        string           `json:"subscriberId"`
	ConnectPoint        string           `json:"connectPoint"`
	AllocationTimeStamp time.Time        `json:"allocationTimestamp"`
	MacAddress          net.HardwareAddr `json:"macAddress"`
	CircuitID           []byte           `json:"circuitId"`
	IPAllocated         net.IP           `json:"ipAllocated"`
	State               int              `json:"state"`
	VlanID              int              `json:"vlanId"`
}

// GetAllocations returns DhcpAllocation info for all devices or for a device ID
func (va *VoltApplication) GetAllocations(cntx context.Context, deviceID string) ([]DhcpAllocation, error) {
	logger.Debugw(ctx, "GetAllocations", log.Fields{"DeviceID": deviceID})
	allocations := []DhcpAllocation{}
	for _, drv := range dhcpNws.Networks {
		drv.sessionLock.RLock()
		for _, session := range drv.sessions {
			vpv, ok := session.(*VoltPortVnet)
			if ok {
				var subscriber string
				// return Name of first service
				vpv.services.Range(func(key, value interface{}) bool {
					svc := value.(*VoltService)
					subscriber = svc.Name
					return false
				})
				// If deviceID is not provided, return all allocations
				// If deviceID exists then filter on deviceID
				if len(deviceID) == 0 || deviceID == vpv.Device {
					allocation := DhcpAllocation{
						SubscriberID:        subscriber,
						ConnectPoint:        vpv.Device,
						MacAddress:          vpv.MacAddr,
						State:               int(vpv.RelayState),
						VlanID:              int(vpv.SVlan),
						CircuitID:           vpv.CircuitID,
						IPAllocated:         vpv.Ipv4Addr,
						AllocationTimeStamp: vpv.DhcpExpiryTime,
					}
					logger.Debugw(ctx, "DHCP Allocation found", log.Fields{"DhcpAlloc": allocation})
					allocations = append(allocations, allocation)
				}
			}
		}
		drv.sessionLock.RUnlock()
	}
	return allocations, nil
}

type MacLearnerInfo struct {
	DeviceID   string `json:"deviceId"`
	PortNumber string `json:"portNumber"`
	VlanID     string `json:"vlanId"`
	MacAddress string `json:"macAddress"`
}

func (va *VoltApplication) GetAllMacLearnerInfo() ([]MacLearnerInfo, error) {
	logger.Info(ctx, "GetMacLearnerInfo")
	macLearner := []MacLearnerInfo{}
	for _, drv := range dhcpNws.Networks {
		logger.Debugw(ctx, "drv found", log.Fields{"drv": drv})
		drv.sessionLock.RLock()
		for _, session := range drv.sessions {
			vpv, ok := session.(*VoltPortVnet)
			if ok {
				macLearn := MacLearnerInfo{
					DeviceID:   vpv.Device,
					PortNumber: vpv.Port,
					VlanID:     vpv.SVlan.String(),
					MacAddress: vpv.MacAddr.String(),
				}
				logger.Debugw(ctx, "MacLerner found", log.Fields{"MacLearn": macLearn})
				macLearner = append(macLearner, macLearn)
			}
		}
		drv.sessionLock.RUnlock()
	}
	return macLearner, nil
}

func (va *VoltApplication) GetMacLearnerInfo(cntx context.Context, deviceID, portNumber, vlanID string) (MacLearnerInfo, error) {
	logger.Info(ctx, "GetMecLearnerInfo")
	macLearn := MacLearnerInfo{}
	for _, drv := range dhcpNws.Networks {
		logger.Infow(ctx, "drv found", log.Fields{"drv": drv})
		drv.sessionLock.RLock()
		for _, session := range drv.sessions {
			vpv, ok := session.(*VoltPortVnet)
			if ok {
				if deviceID == vpv.Device && portNumber == vpv.Port && vlanID == vpv.SVlan.String() {
					macLearn = MacLearnerInfo{
						DeviceID:   vpv.Device,
						PortNumber: vpv.Port,
						VlanID:     vpv.SVlan.String(),
						MacAddress: vpv.MacAddr.String(),
					}
					logger.Infow(ctx, "MacLerner found", log.Fields{"MacLearn": macLearn})
				} else if deviceID == vpv.Device && portNumber == vpv.Port && vlanID == "" {
					macLearn = MacLearnerInfo{
						DeviceID:   vpv.Device,
						PortNumber: vpv.Port,
						VlanID:     vpv.SVlan.String(),
						MacAddress: vpv.MacAddr.String(),
					}
					logger.Infow(ctx, "MacLerner found", log.Fields{"MacLearn": macLearn})
				}
			}
		}
		drv.sessionLock.RUnlock()
	}
	return macLearn, nil
}

func (va *VoltApplication) GetIgnoredPorts() (map[string][]string, error) {
	logger.Info(ctx, "GetIgnoredPorts")
	IgnoredPorts := make(map[string][]string)
	portIgnored := func(key, value interface{}) bool {
		voltDevice := value.(*VoltDevice)
		logger.Infow(ctx, "Inside GetIgnoredPorts method", log.Fields{"deviceName": voltDevice.Name})
		voltDevice.Ports.Range(func(key, value interface{}) bool {
			port := key.(string)
			logger.Infow(ctx, "Inside GetIgnoredPorts method", log.Fields{"port": port})
			//Obtain all VPVs associated with the port
			vnets, ok := GetApplication().VnetsByPort.Load(port)
			if !ok {
				return true
			}
			for _, vpv := range vnets.([]*VoltPortVnet) {
				if vpv.MacLearning == MacLearningNone {
					IgnoredPorts[vpv.Device] = append(IgnoredPorts[vpv.Device], vpv.Port)
				}
			}
			logger.Debugw(ctx, "Ignored Port", log.Fields{"Ignored Port": IgnoredPorts})
			return true
		})
		return true
	}
	va.DevicesDisc.Range(portIgnored)
	logger.Info(ctx, "GetIgnoredPorts completed")
	return IgnoredPorts, nil
}
