diff --git a/internal/pkg/application/dhcprelay.go b/internal/pkg/application/dhcprelay.go
new file mode 100644
index 0000000..06aa3db
--- /dev/null
+++ b/internal/pkg/application/dhcprelay.go
@@ -0,0 +1,1343 @@
+/*
+* 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 (
+	"encoding/hex"
+	"errors"
+	"net"
+	"sync"
+
+	"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"
+	"github.com/opencord/voltha-lib-go/v7/pkg/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(net.HardwareAddr)
+	DhcpResultInd(*layers.DHCPv4)
+	Dhcpv6ResultInd(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 {
+	OuterVlan   uint16
+	InnerVlan   uint16
+	sessions    map[[6]byte]IDhcpRelaySession
+	sessionsv6  map[[MaxLenDhcpv6DUID]byte]IDhcpRelaySession
+	sessionLock sync.RWMutex
+}
+
+// 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.Warn(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.Warn(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(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(dhcp4.ClientHWAddr)
+				}
+				vpv.DhcpResultInd(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(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()
+					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 IsOption82Disabled flag in configuration. if true(disabled), do not 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.IsOption82Disabled {
+			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(device string, port string, pkt gopacket.Packet) {
+	GetApplication().ProcessUDP4Packet(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(device string, port string, pkt gopacket.Packet) {
+	// Currently DHCP is the only application supported by the application
+	// We check for DHCP before proceeding futher. 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(device, port, pkt)
+	} else {
+		// This is a downstream packet
+		va.ProcessDsDhcpv4Packet(device, port, pkt)
+	}
+
+}
+
+// ProcessUDP6Packet : CallBack function registered with application to handle DHCPv6 packetIn
+func ProcessUDP6Packet(device string, port string, pkt gopacket.Packet) {
+	GetApplication().ProcessUDP6Packet(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(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(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(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, isOption82Disabled 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 IsOption82Disabled flag in configuration. if true(disabled), do not add remoteID and circuitID into dhcpv6 header.
+	if dhcpRelay {
+		if !isOption82Disabled {
+			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
+}
+
+// ProcessUsDhcpv6Packet to rpocess upstream DHCPv6 packet
+func (va *VoltApplication) ProcessUsDhcpv6Packet(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.IsOption82Disabled, 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()
+					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(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(clientMac)
+				}
+				vpv.Dhcpv6ResultInd(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()
+}
